;SRC:CHAOS.MAC.397 7-May-81 19:35:46, Edit by MMCM ; Check uniquizer too in CHFNDX ;SRC:CHAOS.MAC.397 2-May-81 12:42:15, Edit by MMCM ; Bug in arpa routing added by use of single temporary packet ;CHAOS.MAC;392 21-Apr-81 17:30:08, Edit by MMCM ; Allow interrupts out of GETOUT hang ;SRC:CHAOS.MAC.375 9-Apr-81 14:54:02, Edit by CPR ; Merge in HIC's 2020 support. ;CHAOS.MAC;373 29-Mar-81 21:08:13, Edit by MMCM ; Don't try to use indexing in previous context on byte instructions. ;SRC:CHAOS.MAC.371 21-Mar-81 14:11:50, Edit by MMCM ;CHAOS.MAC;370 14-Mar-81 13:14:08, Edit by MMCM ; Add conditional assembly for Foonly Tenex. ;SRC:CHAOS.MAC.329 20-Mar-81 15:16:27, Edit by CPR ; Use temporary packet buffer for ARPA to CHAOS routing instead of ; allocating and freeing a packet each time. ;SRC:CHAOS.MAC.327 11-Mar-81 23:29:48, Edit by MMCM ; Fix some bugs with sending over ARPA Net ;SRC:CHAOS.MAC.326 25-Feb-81 16:41:15, Edit by CPR ; Add subnet 13 (EECS pseudo-subnet) to routing tables. ;SRC:CHAOS.MAC.321 20-Feb-81 20:56:46, Edit by CPR ; Fix throwing away of packets-over-window to still mark an NVT ; connection as needing input attention at TTCH7 time; also fix ; case where foreign NCP violating protocol (by sending over window) ; would choke the connection entirely (at CHIDAT): now we just ; throw away a packet when it arrives if it isn't within the real ; receive window (ie, the last user packet # + receive window size). ;SRC:CHAOS.MAC.316 15-Feb-81 18:05:30, Edit by CPR ; Add new form of OPENF: opening "CHA:.-" will get you a connection ; (immediately) through which you can send RFCs to your heart's ; delight, and see all the ANS, FWD, LOS and CLS packets that come ; wafting back in reply. ;SRC:CHAOS.MAC.306 8-Feb-81 18:10:14, Edit by CPR ; Disgusting hack to send over window in SNDPKT after waiting for a ; long time for it to open up; see the "to do" section on how to do ; this right (someday). This is a temporary solution to avoid ; infinite hangage when a connection's window never opens up. ;SRC:CHAOS.MAC.305 6-Feb-81 00:27:51, Edit by CPR ; When opening a listening connection, note that there's some RFC ; matching to do, potentially, to speed up the common case of a ; RFC coming in, not getting matched, and CHARFC starting up a ; server for it, which then listens for that contact name. ;SRC:CHAOS.MAC.304 2-Feb-81 21:25:32, Edit by CPR ; Clear out any references to a connection in CHATTW at RELCON time. ;SRC:CHAOS.MAC.299 28-Jan-81 16:54:03, Edit by CPR ; Super-paranoid locking in SNDPK0 to catch screw where a packet ; is ack'ed illegally by foreign NCP even before it's first ; transmitted (yes, it happens). ;SRC:CHAOS.MAC.295 26-Jan-81 00:13:33, Edit by CPR ; Add variable transmit and receive window sizes for tuning. ;SRC:CHAOS.MAC.264 18-Jan-81 12:19:08, Edit by CPR ; Obey the input "window" for the distinguished RFC handler so that ; if it dies, we won't fill up memory with unhandled-RFC packet copies. ;SRC:CHAOS.MAC.214 12-Jan-81 12:35:55, Edit by CPR ; CHAXMT now calls RELPKM to get rid of a packet when done, in ; the case where it didn't make it onto any send lists and we didn't ; queue it for anywhere. ; Add extra checking for a hung Chaosnet main background fork (done ; by the local routing fork, which has little reason to hang), and ; for a wedged front-end (CHNPO1, fe quota, staying too low for too ; long). ;SRC:CHAOS.MAC.180 9-Jan-81 16:45:33, Edit by CPR ; Make all calls to SNDPK0/SNDPK1 and CHAXMT ask for block/nonblock ; to allow guarantee of never blocking when don't want to; ; add separate background fork for just local routing; ; move actual server startup and shutdown worrying out of monitor ; (opening "CHA:." will let a privileged fork read copies of all ; unhandled RFCs). ;SRC:CHAOS.MAC.168 7-Jan-81 19:53:52, Edit by CPR ; Put back calls to RELPKT for checking's sake only (when debugging, ; will complain if not releasable right away); add "reasons" to RELPKM/T ; calls for debugging; add settable RFC timeout period. ;SRC:CHAOS.MAC.162 2-JAN-80 15:55:56, Edit by JIS ; Fix bug in error return from CPYPKZ ;SRC:CHAOS.MAC.153 22-Dec-80 16:56:46, Edit by CPR ; Always call RELPKM instead of RELPKT since everyone is now careful to ; maintain the link fields of a packet. ;SRC:CHAOS.MAC.108 15-Dec-80 14:32:58, Edit by CPR ; Local routing is now done via background fork (to insulate both sides ; of a connection from each other somewhat). ;SRC:CHAOS.MAC.104 15-Dec-80 12:40:13, Edit by CPR ; Give up on efficiency attempt for Chaos NVT handling: put it back the ; way it was (too slow to be acceptable). ;SRC:CHAOS.MAC.99 14-Dec-80 18:12:08, Edit by CPR ; Attempt at better Chaos NVT has-output handling ; (start-output now sets CF%TTO in an NVT's connection). ;SRC:CHAOS.MAC.78 4-Dec-80 14:08:52, Edit by CPR ; Add debugging code for extra caution in dealing with connections, packets. ; Use HOSTS2.BIN for host table now. General background fork cleanup. ;SRC:CHAOS.MAC.61 3-Dec-80 17:00:58, Edit by CPR ; Add local routing for non-ARPA monitors. ;SRC:CHAOS.MAC.59 3-Dec-80 16:44:12, Edit by CPR ; Let OKSKDP and NOSKDP be called nestedly; wrap them around local ; routing calls to CHIPKT for safety's sake. ;SRC:CHAOS.MAC.58 3-Dec-80 16:25:58, Edit by CPR ; Various changes at EBM's suggestion ;CHAOS.MAC.40 18-Oct-80 04:22:00, Edit by Jis ;206 Add in support for chaos-net-user capability ;SRC:CHAOS.MAC.28 19-Sep-80 13:31:09, Edit by CPR ; Do Chaos NVT input processing at TTCH7 time. ;CHAOS.MAC.22 16-Sep-80 19:50:01, Edit by Jis ; Fix up CPYPKT to have error and nonerror return ;CHAOS.MAC.7 8-Aug-80 11:15:17, Edit by Jis ;199 Don't wait for non-open connections to flush output buffers ;CHAOS.MAC.5 13-Jul-80 22:59:00, Edit by Jis ;197 Allow user to specify RFC packet contents in OPENF call ;<4.MONITOR>CHAOS.MAC.12 8-Feb-80 15:57:37, Edit by MMCM ;166 CHAOSnet packets over the ARPANET to LLL ;<4.MONITOR>CHAOS.MAC.5, 6-Jan-80 01:46:45, Edit by MT ; Fixed up NVT support ;<4.MONITOR>CHAOS.MAC.1 3-Jan-80 05:53:20, Edit by MMCM ; Merged into release 4 MIT-XX standard system REPEAT 0,< -- To do -- -- Doesn't currently support both DECnet and Chaosnet over DN20's (separate, now, of course); in particular, the DEDMCB usage herein doesn't let the DECnet one get control. Will need work in both areas of Chaos and DECnet support. -- The various calls to UNLDIS herein are probably not right: they have NOINTs after them to re-lock up processarily, but this doesn't re-lock the JFN they're dealing with. Have to figure how to do that right in each case. -- net-independent CVHST, GTHST, etc. (needs thought) -- at CHAXMT, we now never send a packet when the -11 is over quota, and this helps solve the problem of the -11 getting a message when it has no buffer space and crashing (in the case of 20F) or simply ignoring the message (and thus no ack ever comes back from the -11), which means we lose track of the -11 status. However, this has the bad side effect that short control messages generated at interrupt level (eg, STS to stop duplicate retransmissions) mightn't get out when they should. A better solution is to reserve some "interrupt level" space in the -11 as well as normal, process-level packet space, and to use them separately, with the -11 reporting every second or so on its space situation to keep the -10 in synch with both types of space. -- at SNDPKT, we just go ahead and send over-window after a timeout period, to avoid being locked up there forever (happens alot). The real solution, of course, is to re-arrange things so that SNDPKT queues up packets to be sent when the window opens up, and requests a BLKF (thus unlocking) from its various callers, with the callers prepared to restart. -- when someone attempts to listen for a connection name, that really shouldn't fail if someone else is already listening unless the first listener requested exclusive access in the OPENF%. Otherwise, it is hard to have "shelf" jobs, several of which can be waiting, listening for a connection. This would require reorganizing the RFC-listening stuff (couldn't use a TBLUK% table any more), but it's worth it. -- There is still some lossage with performance apropos packet pool usage: a very active connection can nearly monopolize the interrupt- level pool, making it hard for other connections to get their work done; I'm currently playing with maximum window settings to see if tweaking these can help. -- There is also lossage in CLSWAT, where, in theory, we should be able to just wait for the transmit window to totally open up to ensure all packets got out safely. However, this doesn't work. Figure out why (it seems to confuse ITS NCPs). >;REPEAT 0, SEARCH PROLOG IFN ARPAF, IFNDEF FRNDLY, ;FRIENDLY HOST SUPPORT CODE IFN FRNDLY,< DEFINE FRIEND (SITE) < IRP SITE,< [ASCIZ /SITE/] >>> ;;;DEBUGGING/METERING SETTINGS IFNDEF CHSDBG, ;DEBUGGING ON BY DEFAULT IFNDEF CHSMTR, ;METERING OFF BY DEFAULT ;;;FLAGS DOUBLE-CHECKEROO IFE , IFG -1, IFN ARPAF&SMFLG, IFN &TNXFLG, IFN DTEFLG&SMFLG, IFN T20FLG&F3FLG, IFN DTEFLG,< ;CHECK ON DTE CONFIGURATION IFL NETDTE, IFGE NETDTE-4, >;IFN DTEFLG, ;+++IFN DTEFLG&<1-NETDTE>, ;IF GOING THROUGH PRIMARY DTE IFN T20FLG,< TTITLE CHAOS IFN KLFLG, ;GET DTE DEFINITIONS IFN SMFLG, ;GET CHAOS UNIBUS ADAPTER DEFINITIONS EXTN DEFINE CHABUG (X,Y) )> ;COMPATIBLE BUG MACRO FOR BOTH SYSTEMS OPDEF XCTUM [XCTU] ;DATA ONLY IN PREVIOUS CONTEXT >;IFN T20FLG IFN TNXFLG,< SEARCH STENEX,MONSYM,MACSYM TITLE CHAOS EXTN EXTN EXTN EXTN EXTN >;IFN TNXFLG SUBTTL DEFINITIONS DEFINE DEBUG DEFINE NODEB ;EXTERNAL REFERENCES EXTN ;CHAOS PACKET LIMITS EXTN EXTN EXTN EXTN EXTN EXTN EXTN ;TABLE, HAVE-TABLE, # PAGES, NET # EXTN ;OFFSET IN CHOSTB OF CHAOS ADDRESS TABLE EXTN EXTN EXTN EXTN EXTN DEBUG,< EXTN > ;FOR DEBUGGING ONLY: FREE POOL BEGINNING AND END IFN DTEFLG,> IFN DTEFLG,> IFN SMFLG,< EXTN EXTN > IFN ARPAF,< ;166 EXTN EXTN >;IFN ARPAF, IFE ARPAF,< EXTN >;IFE ARPAF, DEBUG,> DEFINE CHKCON < ;;;CHECK THE CONNECTION REF'ED BY CONN IF DEBUGGING DEBUG,< CALL CHKCNB > > DEFINE TCHKCN < ;;;CHECK THE CONN REF IN T1; FOR USE IN SCHED TESTS DEBUG,< PUSH P,CONN HRRZI CONN,(T1) CHKCON POP P,CONN >> DEFINE CHKPKT < ;;;CHECK THE PACKET REF'ED BY PKT IF DEBUGGING DEBUG,< CALL CHKPKB > > DEFINE TCHKPK < ;;;CHECK PACKET REF IN T1; FOR USE IN SCHED TESTS DEBUG,< PUSH P,PKT HRRZI PKT,(T1) CHKPKT POP P,PKT >> DEFINE PKTPTH (PI) < ;;;NOTE PACKET HAS GONE BY THIS POINT IN ITS PATH DEBUG,< MOVE CX,PI CALL PKTPTS >> DEFINE CONPTH (PI) < ;;;NOTE CONNECTION HAS BEEN BY THIS POINT DEBUG,< MOVE CX,PI CALL CONPTS >> DEFINE RCALL (RTN,R) < ;;;CALL A ROUTINE WITH A 'REASON' WHEN DEBUGGING DEBUG,< MOVX CX,R > ;GET THE REASON CODE IN CX FOR THE CALL CALL RTN > DEFINE METER DEFINE NOMET METER,> IFN DTEFLG,< CHADTE==NETDTE ;USE THE NETWORK -11'S DTE IF THERE IS ONE IFE CHADTE,> ;THROUGH PRIMARY DTE, NEED ASSEMBLY AREA IFN CHADTE,> ;SECONDARY DTE: INVALID PROTOCOL CALL >;IFN DTEFLG IFE DTEFLG, ;PI CHANNEL ASSIGNMENT CHACHN==-1 ;BY DEFAULT, NO PI CHANNEL ASSIGNMENT IFN T20FLG,< ;BUT UNDER TWENEX, ONE OF: IFN KLFLG, ; KL: CHAOS HANDLING VIA DTE'S (DLS LEVEL) IFN SMFLG, ; KS: VIA UNIBUS ADAPTER'S LEVEL >;IFN T20FLG, ;LOCAL AC'S DEFAC(CONN,Q1) DEFAC(PKT,Q3) ;FILESYS AC'S IFN T20FLG,< DEFAC(STS,P1) DEFAC(JFN,P2) DEFAC(DEV,P4) DEFAC(F1,P5) > ;FILESYSTEM STORAGE USAGE FILCON==FILOFN ;LOS ERROR STRING ADDR,,CONNECTION BLOCK ;FILBFO==FILMS1 ;OUTPUT BUFFER POINTER ;FILBFI==FILMS2 ;INPUT BUFFER POINTER ;FILBCT==FILFDB ;BYTE COUNTS OUTPUT,,INPUT FILOBF==FILCOD ;OUTPUT BUFFER PACKET ADDR IF1,< ;PACKET HEADER FORMAT (DESCRIBED IN REVERSE FORMAT SINCE IT GROWS BACKWARDS) DEFINE PHE (E,L) < ;;;PACKET HEADER ENTRY IFB , IFNB,> E==-PKTHLN > PKTHLN==0 ;INITIALIZE HEADER LENGTH IFN CHADTE!CHDR11,< IFN CHADTE,< PHE PKTTYP ;NEED THIS TYPE FOR TO -11 PTCL >;IFN CHADTE IFN CHDR11,< PHE PKTCDR ;SIZE (16-BIT BYTES),,CDR FOR DR11 MICROCODE >;IFN CHDR11 IFN ARPAF,< ;UNLESS DOING ARPA ROUTING, WHEN NEED PHE PKTIMP,3 ; 4 WORDS FOR ARPANET HEADER, SHARING ROOM >;IFN ARPAF ; WITH TO -11 HEADER >;IFN CHADTE!CHDR11 DEBUG,< PHE PKTMAG ;MAGIC WORD FOR EXTRA CHECKING PHE PKTHSP ;PACKET HISTORY BYTE PTR (MUST PRECEDE PKTHST!) PHE PKTHST,3 ;PACKET HISTORY: 6-BIT PATH NUMBERS PHE PKTHDW ;COPY OF ORIGINAL PACKET ASGRES HEADER >;DEBUG PHE PKTTIM ;TIME OF LAST ACTIVITY WITH THIS PACKET IFN SMFLG, ;RE-XMISSION COUNT,,LINK TO NEXT PKT TO BE XMITTED PHE PKTLNK ;LINK WORD: ,, ; PURGE PHE >;IF1 ;PACKET-HANDLING MACRO: ON KS10, WE TRY TO AVOID FREEING AND THEN ;IMMEDIATELY RE-ALLOCATING PACKETS, SO USE GETPKT INSTEAD OF CALLING ;CPYPKI DIRECTLY TO COPY AN INPUT PACKET. IF SIZE ARG IS NOT BLANK, ;THEN T3 HAS NUMBER OF BYTES NEEDED. ;RETURNS +1 ON FAILURE. DEFINE GETPKT(SIZE) < IFN SMFLG,< IFNB ,< CALL CPYPKI >> IFE SMFLG,< IFNB , CALL CPYPKT >> ;MISCELLANEOUS IFN .CSCLS, ;TIME CONSTANTS CHTRFW==^D<30*1000> ;DEFAULT MS TO WAIT FOR RFC ANSWER ;OTHER PARAMETERS IFN SMFLG,< CHARTC==3 ;RETRANSMIT THIS MANY TIMES IF XMIT ABORTS > ;;STATUS ANS BYTE COUNT IFN SMFLG,> ;KS REPORTS ALL 8 REAL PACKET COUNTERS IFE SMFLG,> ;OTHERS REPORT ONLY IN AND OUT COUNTERS SUBTTL INITIALIZATION & PTCL VECTORS ;INITIALIZE NETWORK STUFF SWAPCD ;OK TO BE SWAPPABLE CHAINI::SETOM CHCNLK ;UNLOCK CONNECTION LOCK SETOM CHRFLK ;AND RFC TABLE LOCK SETZM CHQRFC ;EMPTY OUT INCOMING RFC QUEUE SETOM CHATTW ;EMPTY OUT NVT-CONNECTION-WITH-DATA Q MOVE 1,[CHATTW,,CHATTW+1] BLT 1,CHATTW+NTTCVT ;CLEAR OUT WHOLE TABLE SETOM CHPIDF ;SET UP PI LOCKING VARIABLES SETZM CHAPRO ;206 DEFAULT IS NO NET PROTECTION SETZM CHOSTP ;NO HOST TABLE BUILT YET SETZM MYHNAM ;I DON'T HAVE A NAME YET, EITHER SETOM MYCHAD ;INDICATE WE DON'T KNOW OUR HARDWARE ADDRESS YET SETZM CHQLCL ;CLEAR OUT LOCAL-ROUTING QUEUE MOVEI T1,^D488 ;LARGEST NUMBER OF BYTES PER PACKET MOVEM T1,CHPMXC ;SET IT FOR EVERYONE TO FIND IFN DTEFLG,< IFE CHADTE,< ;BUT THIS IS LARGEST WE CAN TRANSMIT THROUGH MOVEI T1,300 ; PRIMARY FRONT END >>;IFE CHADTE & IFN DTEFLG MOVEM T1,CHPMXT ;LARGEST TRANSMITTABLE PACKET SIZE ADDI T1,3 ;CALCULATE MAXIMUM NUMBER OF WORDS THIS LSH T1,-2 ; IMPLIES MOVEM T1,CHPMXW MOVEI T1,CHRFMX ;MAXIMUM NUMBER OF RFC'S ALLOWED MOVEM T1,RFCTAB ;INIT TABLE OF CONNECTION NAMES FOR THEM MOVX T1,5 ;NOMINAL WINDOW SIZE (VARIABLE FOR TWIDDLING) MOVEM T1,NMWIND MOVX T1,^D10 ;MAXIMUM WINDOW SIZES MOVEM T1,MXRWIN ;(KEEP THIS REASONABLE SO WE DON'T LET ONE MOVX T1,^D15 ; CONNECTION EAT ALL THE INTERRUPT-LEVEL POOL) MOVEM T1,MXTWIN IFE ARPAF,< CALL NVTINI ;CLEAR OUT NVT TABLES IF ARPANET WON'T DO IT > MOVSI T1,(CR%CAP) ;CREATE LOCAL-ROUTING FORK SETZ T2, CFORK ;MAKE A JOB0 FORK CHABUG(CHLFRK) MOVEI T2,CHALRF ;START IT UP MSFRK SETZM CHAFLG ;CLEAR BACKGROUND FORK REQUEST FLAGS MOVSI T1,(CR%CAP) ;GIVE IT ALL OUR CAPABILITIES SETZ T2, CFORK ;MAKE A JOB0 FORK CHABUG(CHIFRK) MOVEI T2,CHSFRK ;START IN MONITOR MODE MSFRK JRST CHARLD ;AND HANDLE LIKE RELOAD RESCD ;THIS CALLED FROM DTE INT LEVEL IFN DTEFLG,< IFN CHADTE,< CHADTV::CHAPKT ;DATA IS A PACKET NSPQER ;SHOULD NEVER REQUEST STATUS CHSSTS ;HERE IS STATUS CHADON ;ACK OF PACKET SENT >;IFN CHADTE IFE CHADTE,< ;DTE PTCL VECTOR FOR CHAOS INTERFACE CHADTV::CHAHSD ;STRING DATA (PACKET) CHADON ;ACK CHSSTS ;STATUS FROM -11 0 ;SET LINE ALLOCATION 0 ;SYSERR CHARLD ;-11 RELOAD ACTION >;IFE CHADTE >;IFN DTEFLG SWAPCD ;OK TO BE SWAPPABLE ;CHA: DEVICE DTB CHADTB::DTBDSP (CHADIR) ;DIRECTORY LOOKUP DTBDSP (CHANAM) ;NAME LOOKUP DTBDSP (CHAEXT) ;EXTENSION LOOKUP DTBDSP (CHAVER) ;VERSION LOOKUP DTBBAD (DESX9) ;NO PROTECTION DTBBAD (DESX9) ;NOR ACCOUNT DTBBAD (DESX9) ;NOR STATUS DTBDSP (CHAOPN) ;OPENF DTBDSP (CHASQI) ;SEQUENTIAL INPUT DTBDSP (CHASQO) ;SEQUENTIAL OUTPUT DTBDSP (CHACLZ) ;CLOSF REPEAT 7,< DTBBAD (DESX9)> ;RANDOM ILLEGAL FUNCTIONS DTBDSP (CHAMTO) ;MTOPR DTBDSP (CHASTS) ;GET STATUS DTBBAD (DESX9) ;SET STATUS IFN T20FLG,< DTBDSP (CHASQR) ;SOUTR DTBDSP (RFTADN) ;NO READ TOD DTBDSP (SFTADN) ;NOR SET TOD DTBDSP (CHAINP) ;SET FOR INPUT DTBDSP (CHAOUP) ;SET FOR OUTPUT DTBBAD (GJFX49) ;ATTRIBUTES >;IFN T20FLG SUBTTL GTJFN AND OPENF DEVICE ROUTINES ;DIRECTORY LOOKUP CHADIR: TQNE ;STEPPING DIRECTORIES NOT ALLOWED RETBAD (GJFX17) NOINT JRST SK2RET ;SKIP RETURN WITH INTERRUPTS OFF ;VERSION LOOKUP CHAVER: JUMPGE T1,OKRET TQNE ;TRYING TO STEP? RETBAD (GJFX18,) ;YES, ERROR OKRET: TQNN ;OK TO UNLOCK? OKINT ;YES, TURN BACK ON INTERRUPTS JRST SK2RET ;NAME LOOKUP CHANAM: JUMPE T1,[RETBAD (GJFX18,)] ;WILDCARDS NOT ALLOWED CALL HSTNAM ;GET HOSTNAME RETBAD (GJFX18,) ;NO GOOD JRST OKRET ;EXTENSION LOOKUP CHAEXT: JUMPE T1,[RETBAD (GJFX18,)] ;WILDCARDS NOT ALLOWED JRST OKRET ;ELSE LOOKS ALRIGHT ;CHA: DEVICE OPENF CHAOPN: SKIPL MYCHAD ;DO I KNOW MY HARDWARE ADDRESS YET? SKIPN CHAON ;IS THE NETWORK IN FACT THERE YET? RETBAD (OPNX19) ;NO OR NO SKIPE CHAPRO ;IS NET PROTECTION ON? JRST [ MOVE T1,CAPMSK ;YES, CHECK POTENTIAL CAPAS TRNE T1,SC%WHL!SC%OPR!SC%CHA ;DO WE HAVE REQUIRED CAPAS? JRST .+1 ;YEP, GO ON... RETBAD(CHAOX5)] ;NO, GIVE ERROR TQZE ;APPEND TQO ;BECOMES WRITE TQNN ;SOME SORT OF ACCESS THERE? RETBAD (OPNX14) ;NO, BAD OPENF LDB PKT,PBYTSZ ;GET BYTE SIZE REQUESTED CAIE PKT,10 ;FOR NOW ONLY ALLOW 8-BIT BYTE CONNECTIONS CAIN PKT,7 ;OR ASCII FOR SIMPLICITY CAIA RETBAD (SFBSX2) ;ILLEGAL BYTE SIZE LOCK CHCNLK, ;LOCK UP THE CONNECTION LOCK MOVSI CONN,-MAXCON ;MAXIMUM NUMBER OF NETWORK CONNECTIONS ALLOWED SKIPGE CHACON(CONN) ;THIS CONNECTION IN USE? AOBJN CONN,.-1 ;YES, KEEP LOOKING JUMPGE CONN,CHOPX4 ;INSUFFICIENT RESOURCES CALL ASGPAG ;GET A FREE PAGE +++SHOULD THIS CALL ASGPGS??? JRST CHOPX4 ;FAILED, UNLOCK LOCK AND RETURN HRRM T1,FILWND(JFN) ;SAVE IT FOR BUFFER MOVE T1,[.RESP1,,CONSIZ] ;WHEN DEBUGGING, NEED PAGE-FAULT-FREENESS MOVEI T2,.RESNP ;FROM THE NETWORK POOL CALL ASGRES ;ASSIGN ZEROED RESIDENT STORAGE FOR IT JRST CHOPX3 ;FAILED, UNLOCK LOCK AND RETURN HLRZ T2,CHACON(CONN) ;GET UNIQUIZER ANDI T2,400000-1_12 ;JUST UNIQIZER PART CAIN T2,400000-1_12 ;MAXIMUM? SETZ T2, ;YES, WRAP AROUND ADDI T2,1_12(CONN) ;INCREMENT UNIQUIZER AND ADD IN LOCAL IDX STOR T2,CHAIDX,(T1) ;STORE IN CONNECTION BLOCK HRLI T1,400000(T2) ;SET CONNECTION IN USE MOVEM T1,CHACON(CONN) ;SAVE THIS INDEX THEN UNLOCK CHCNLK ;DONE WITH CONNECTION LOCK HRRZ CONN,T1 ;AND KEEP CONVENIENT FOR US LATER DEBUG,< MOVE T2,[CHSMGV] ;SET IN MAGIC VALUE IF DEBUGGING XORI T2,(CONN) ;MAKE IT KEYED TO CONNECTION IN QUESTION MOVEM T2,CONMAG(CONN) MOVEI T1,CONHST(CONN) ;BUILD HISTORY BYTE REF HRLI T1,331100 MOVEM T1,CONHSP(CONN) CONPTH [1] ;NOTE GENESIS FOR CONNECTIONS >;DEBUG HRRZM CONN,FILCON(JFN) ;SAVE BLOCK WITH JFN STOR PKT,CHABSZ,(CONN) ;STORE BYTE SIZE AWAY MOVE T1,MYCHAD ;PUT IN LOCAL HOST ADDRESS STOR T1,CHALCH,(CONN) MOVE T1,FORKX ;SAVE OWNING FORK STOR T1,CHAFRK,(CONN) SETONE CHAICN,(CONN) ;NO CHANNEL TO INTERRUPT YET SETONE CHAOCN,(CONN) MOVE T1,NMWIND ;NOMINAL WINDOW SIZE TO START HRLM T1,CHAWIN(CONN) ;RECEIVE WINDOW SIZE MOVX T1,CHTRFW ;DEFAULT RFC WAIT TIMEOUT PERIOD STOR T1,CHATRF,(CONN) HLRZ T1,FILNEN(JFN) ;GET POINTER TO NAME STRING CALL HSTNAM ;LOOKUP HOST NAME JRST [ MOVEI T1,GJFX18 JRST CHOPX1 ] JUMPE T1,CHOPIN ;IF NULL, WANTS TO LISTEN ;WANTS TO INITIATE AN RFC TO SOMEPLACE STOR T1,CHAHST,(CONN) ;SAVE REMOTE HOST DESIRED MOVE T1,TODCLK ;TIME OF LAST ACTIVITY MOVEM T1,CHAITM(CONN) MOVEI T1,.CSRFS ;RFC SENT STATE HRRM T1,CHASTA(CONN) MOVEI Q2,.CORFC ;REQUEST FOR CONNECTION RCALL ASGPKC,30 ;ALLOCATE A PACKET FOR THIS CONNECTION JRST [ MOVEI T1,MONX01 JRST CHOPX1 ] HRRZ T2,FILNEN(JFN) AOJ T2, MOVE T1,T2 HRLI T1,() ;SAVE CONTACT NAME POINTER ILDB T1,T1 ;GET FIRST BYTE OF CONTACT NAME JUMPE T1,[CALL CHOPI3 ;IF ZERO (NULL CONTACT NAME) JRST [MOVEI T1,CHAOX3 ;FILL IN RFC FROM USER AC3 JRST CHOPX1] ;FAILED JRST CHOPI0] ;GO SEND IT CALL PKTSTR ;FILL IN PACKET DATA FROM STRING AND SEND IT CHOPI0: SETZ T1, CALL SNDPK0 ;SEND THIS OFF, BLOCKING IS OK HRRI T1,RFCST ;RFC SENT HANDLING TEST CHOPI1: LOAD T2,IOMODE ;GET DATA MODE CAIE T2,6 ;6 OR 7 IS IMMEDIATE RETURN CAIN T2,7 RETSKP CONPTH [2] ;NOTE WE'VE BEEN THIS ROUTE HRLI T1,(CONN) ;CONNECTION INDEX CALL CHOWAT ;WAIT FOR OPEN HRRZ T1,CHASTA(CONN) ;GET CONNECTION STATE NOW JUMPE T1,[HLRZ T1,CHAIBF(CONN) ;CLOSED, SEE IF THERE IS ANY DATA JUMPE T1,CHOPI2 LOAD T1,CPKOP,(T1) ;IS IT A DATA TYPE PACKET CAIE T1,.COANS ;ANS IS ACCEPTABLE DATA FOR THIS CAIL T1,.CODAT RETSKP JRST CHOPI2] ;NO, MUST BE LOSING CAIE T1,.CSRFC CAIN T1,.CSOPN ;OPENED OK? RETSKP ;YES, RETURN OK CAIE T1,.CSLOS ;LOS RECEIVED FROM IT? SKIPA T1,[OPNX20] ;NO, MUST HAVE TIMED-OUT AND GONE INC CALL GETLOS ;YES, SET UP ERROR MESSAGE FROM THAT CHOPX1: PUSH P,T1 ;SAVE ERROR CODE HRRZ T1,FILWND(JFN) CALL RELPAG ;GET RID OF INPUT WINDOW PAGE CALL RELCON ;RELEASE THE STORAGE BLOCK POP P,T1 RET ;ERROR RETURN ;WAIT FOR CONNECTION TO OPEN, MDISMS ARG IN 1 IFN T20FLG,< CHOWAT: PUSH P,T1 ;SAVE MDISMS ARGUMENT MOVEI T1,(CONN) ;SETUP FOR CONNECTION TO GET DEALLOCATED IF USER ^C'S MOVEI T2,STKCD5 CALL JSBSTK POP P,T1 ;GET BACK MDISMS ARG CALL UNLDIS ;WAIT FOR THAT STATE TO OCCUR NOINT ;PROTECT OURSELVES MOVEI T1,(CONN) ;FLUSH DEALLOCATION RECORD MOVEI T2,STKCD5 CALLRET JSFRMV ;REMOVE FROM JSB STACK NOW THAT NOINT AGAIN >;IFN T20FLG IFN TNXFLG,< CHOWAT: MDISMS ;WAIT FOR IT RET ;AND RETURN >;IFN TNXFLG CHOPI2: MOVEI T1,OPNX21 JRST CHOPX1 ;HERE TO FILL IN RFC FROM DATA REF'ED BY USER AC3 CHOPI3: SAVEAC ;NOT SURE THIS IS NECESSARY XCTUM [HLRZ T1,3] ;GET USER SUPPLIED BYTE COUNT CAMLE T1,CHPMXT ;CURRENT BYTE COUNT LIMIT RET ;PUNT IF TOO MUCH DATA PUSH P,T1 ;SAVE BYTE COUNT FOR LATER ADDI T1,3 ;ROUND APPROPRIATELY LSH T1,-2 ;199 CONVERT TO WORD COUNT XCTUM [HRRZ T2,3] ;USER ADDRESS TO COPY FROM XMOVEI T3,CHPKDT(PKT) ;POINTER TO DATA AREA OF PACKET CALL BLTUM ;COPY AWAY... POP P,T1 ;RECLAIM BYTE COUNT STOR T1,CPKNB,(PKT) ;STORE IN PACKET HEADER RETSKP ;WON CHOPX3: HRRZ T1,FILWND(JFN) CALL RELPAG ;GET RID OF INPUT WINDOW PAGE CHOPX4: UNLOCK CHCNLK ;UNLOCK CONNECTION LOCK RETBAD (MONX01) ;UNSUFFICIENT RESOURCES RESCD RFCST: TCHKCN ;IF DEBUGGING, CHECK CONNECTION HRRZ T2,CHASTA(T1) CAIE T2,.CSRFS ;STILL RFC SENT STATE? JRST 1(4) ;NO, RETURN IFN T20FLG,< JRST 0(4) >;IFN T20FLG IFN TNXFLG,< RFCST1: MOVE T3,FKINT(FX) ;LOOK FOR DEFERRED INTERRUPTS TLNN T3,(1B1) JRST 0(4) ;NONE, CONTINUE BLOCKED MOVEI T2,.CSINC ;WAS ONE, TIME CONNECTION OUT HRRM T2,CHASTA(T1) JRST 1(T4) >;IFN TNXFLG SWAPCD ;HERE TO LISTEN FOR A CONNECTION (CHA:.FOO), TO BECOME THE DISTINGUISHED RFC ;HANDLER (CHA:.) OR TO SET UP A RFC/ANS PERMANENT CONNECTION (CHA:.-) CHOPIN: HRRZ T2,FILNEN(JFN) ;GET CONNECTION NAME TO LISTEN FOR HRLI T2,() MOVE T1,T2 ;NOW, SEE IF THIS ILDB T3,T1 ; NAME IS NULL (WANTS TO LISTEN FOR ALL RFCS) JUMPE T3,[MOVX T2,SC%WHL!SC%OPR!SC%NWZ!SC%NAS ;YES, CHECK CAPAS MOVX T1,NTWZX1 ;ERROR CODE IF NOT PRIVILEGED TDNN T2,CAPMSK ; (POTENTIAL IS GOOD ENOUGH) JRST CHOPX1 ;NO, GO CLEAN UP AND RETURN ERROR NOSKED ;ACQUIRE THIS CAREFULLY MOVX T1,OPNX9 ;INVALID SIMULTANEOUS ACCESS IF ALREADY A LISTENER SKIPE CHRFHC ;SOMEONE ALREADY THERE? JRST [ OKSKED ;YES, UNLOCK JRST CHOPX1 ] ; AND GIVE ERROR MOVEM CONN,CHRFHC ;NO, WE'RE NOW THE FELLOW IN COMMAND OKSKED MOVX T1,^D20 ;THIS SHOULD BE ENOUGH INPUT WINDOW FOR IT, HRLM T1,CHAWIN(CONN) ; ASSUMING IT'S FAIRLY RESPONSIVE MOVX T1,.CSLSN ;PRETEND WE'RE LISTENING, BUT HRRM T1,CHASTA(CONN) RETSKP ] ; RETURN SUCCESS IMMEDIATELY CAIN T3,"-" ;PERHAPS WANTS TO SET UP A PERMANENT RFC-SENT JRST [ ILDB T3,T1 ; CONNECTION? ("CHA:.-") JUMPN T3,.+1 ;NOPE MOVX T1,.CSPRF ;YES, SAY SO AND HRRM T1,CHASTA(CONN) ; SUCCEED RETSKP ] ; IMMEDIATELY CALL ADDLSN ;ADD NEW CONNECTION NAME JRST CHOPX1 ;FAILED: ERROR CODE IN T1 ALREADY MOVX T1,CH%RFC ;TELL THE BACKGROUND FORK TO CHECK AGAIN IORM T1,CHAFLG ; FOR POTENTIAL RFC MATCHES MOVX T1,.CSLSN ;LISTENING STATE HRRM T1,CHASTA(CONN) HRRI T1,RFCRT ;WAIT FOR AN INCOMING RFC JRST CHOPI1 RESCD RFCRT: TCHKCN ;IF DEBUGGING, CHECK CONNECTION HRRZ T2,CHASTA(T1) CAIE T2,.CSLSN ;STILL LISTENING? JRST 1(4) ;NO, RETURN IFN T20FLG, IFN TNXFLG, ;CHECK FOR USER ^C'ING AS WELL SWAPCD ;ADD STRING REF'ED BY T2 TO THE LISTENING RFC LIST; RETURN NONSKIP WITH ;T1/ ERROR CODE IF THERE ARE PROBLEMS. ADDLSN: STKVAR MOVEM T2,ADLSAD ;SAVE STRING LOCK CHRFLK, ;GET THE RFC TABLE LOCK MOVEI T1,RFCTAB ;RFC LISTENING TABLE TBLUK ERJMP ADDLSR ;SOME PROBLEM, LUMP UNDER 'NO RESOURCES' TXNE T2,TL%EXM ;EXACTLY MATCHED SOMETHING ALREADY THERE JRST ADDLSF ; SO RETURN ERROR MOVE T2,ADLSAD ;GET BACK STRING POINTER SETZ T3, ILDB T1,T2 JUMPE T1,.+2 AOJA T3,.-2 ;COMPUTE LENGTH MOVEM T3,ADLSCT ;SAVE COUNT AOJ T3, ;BUMP UP FOR ENDING NULL MOVEI T1,5+4(T3) ; PLUS ONE WORD FOR HEADER IDIVI T1,5 ;GET DESIRED LENGTH CALL ASGSWP ;GET SOME SWAPPABLE SPACE JRST ADDLSR ;FAILED, RESOURCE PROBLEM MOVE T3,ADLSCT ;RECOVER COUNT MOVSI T2,1(T1) ;BUILD STRING REF IN LH FOR TBLUK FORMAT EXCH T2,ADLSAD ;SAVE ADDRESS, GET ORIGINAL STRING PTR HRLI T1,() ILDB PKT,T2 IDPB PKT,T1 SOJG T3,.-2 SETZ PKT, IDPB PKT,T1 ;TIE OFF TO MAKE ASCIZ MOVE T2,ADLSAD ;GET BACK CONTACT NAME REF HRRI T2,(CONN) ;BUILD CONTACT REF,,CONNECTION TO HANDLE THIS RFC MOVEI T1,RFCTAB ;PUT THIS NEW ENTRY INTO TABLE TBADD ERJMP ADDLSR ;IF TABLE FULL, FAIL UNLOCK CHRFLK RETSKP ADDLSR: SKIPA T1,[MONX01] ;RESOURCE PROBLEM HERE ADDLSF: MOVEI T1,OPNX9 ;NAME ALREADY EXISTS: INVALID SIMULTANEOUS ACCESS UNLOCK CHRFLK ;FAILED SOMEHOW: UNLOCK RET ; AND INDICATE FAILURE ;CHAOS NET CLOSF CHACLZ: HRRZ CONN,FILCON(JFN) ;GET CONNECTION INDEX CHKCON ;VALIDATE IT IF DEBUGGING HRRZ Q2,CHASTA(CONN) ;AND STATE CAIN Q2,.CSRFC ;RFC RECEIVED? JRST CHACL2 ;YES, STILL NEED TO SEND A CLS FOR IT CAIE Q2,.CSOPN ;STILL OPEN? JRST CHACL3 ;NO, SKIP SENDING ANYTHING CALL CHARTR ;YES, TRY TO RETRANSMIT WHATEVER NEEDS IT CALL FLSOUT ;SEND OFF LAST PACKET TQZ ;IGNORE ERROR UMOVE T1,1 TDNN T1,[1,,400000] ;IF NOT CALLED FROM CLOSF TLNN T1,(CO%WCL) ;OR NOT REQUESTED JRST CHACL2 ;DONT WAIT FOR IT TO GET DONE MOVSI T1,(CONN) HRRI T1,CLSWAT ;WAIT FOR ALL DATA TO GET SENT OUT IFN T20FLG,< CALL UNLDIS NOINT >;IFN T20FLG IFN TNXFLG,< MDISMS >;IFN TNXFLG CHACL2: MOVEI Q2,.COCLS RCALL ASGPK0,31 ;GET A PACKET FOR CONNECTION WITHOUT DATA JRST CHACL3 SETZ T1, CALL SNDPK0 ;SEND IT OFF TOO, BLOCKING OK CHACL3: CALL RELCON ;RELEASE STORAGE ASSOCIATED WITH THIS CONNECTION AOS (P) ;WILL SKIP RETURN CHACL4: SKIPE PKT,FILOBF(JFN) ;HAVE AN OUTPUT BUFFER? JRST [ RCALL RELPKT,3 ;YES, FREE IT TOO JRST .+1 ] HRRZ T1,FILWND(JFN) SKIPE T1 CALL RELPAG SETZM FILBFO(JFN) SETZM FILBFI(JFN) HLRZ T2,FILCON(JFN) ;LOS ERROR MESSAGE STILL? JUMPE T2,R ;NO, DONE HRRZS (T2) MOVEI T1,JSBFRE CALL RELFRE ;RELEASE IT HRRZS FILCON(JFN) RET ;WAIT UNTIL ALL PACKETS FOR CONNECTION HAVE BEEN SENT OFF RESCD CLSWAT: TCHKCN ;IF DEBUGGING, CHECK CONNECTION HRRZ T2,CHASTA(T1) ;199 CHECK FOR NON-OPEN CONNECTION CAIE T2,.CSOPN ; BETTER BE OPEN JRST 1(T4) ; UNBLOCK IF NOT ;+++ THIS APPEARS TO BE WRONG: YOU REALLY WANT TO WAIT UNTIL ALL PACKETS ;+++ HAVE BEEN GIVEN TO THE REMOTE FELLOW, NOT JUST RECEIPTED. HLRZ T2,CHAOBF(T1) ;GET HEAD OF CONNECTION OUTPUT PACKET LIST JUMPE T2,1(T4) ;NONE, UNBLOCK REPEAT 0,< ;+++ HOWEVER, THIS DOESN'T WORK QUITE RIGHT! HRRZ T2,CHAWIN(T1) ;PICK UP CURRENT XMIT WINDOW CAMG T2,CHANOS(T1) ;SEE IF STILL THINGS TO BE ACK'ED JRST 1(T4) ;NO, UNBLOCK >;REPEAT 0, IFN T20FLG, ;YES, KEEP WAITING IFN TNXFLG, ;RELEASE ALL STORAGE ASSOCIATED WITH A CONNECTION; SET THINGS UP SO ;AN INACTIVE CONNECTION WILL BE RECOGNIZED BY THE VARIOUS CONNECTION AND ;QUEUE MUNGING ROUTINES. RELCON::CHKCON ;POSSIBLY CHECK THIS CONNECTION FOR VALIDITY CALL NOSKDP MOVEI Q2,CHAPBF(CONN) ;OUT OF ORDER PACKETS CALL CHALFR SETOM CHAPBF(CONN) ;MARK THIS Q AS INACTIVE NOW MOVEI Q2,CHAIBF(CONN) ;INPUT BUFFERS CALL CHALFR SETOM CHAIBF(CONN) ;THIS Q IS INACTIVE CALL CHALFO SETOM CHAOBF(CONN) ;DITTO SETZM CHANBF(CONN) CAMN CONN,CHRFHC ;IS THIS THE DISTINGUISHED RFC HANDLER? SETZM CHRFHC ;YES, NO LONGER THERE CALL CH7CLN ;GET RID OF ANY QUEUED-FOR-INPUT REFS MOVN T1,RFCTAB ;CHECK THAT IT IS NOT IN THE RFC TABLE HRRI T1,RFCTAB AOBJP T1,RELCN2 RELCN1: HRRZ T2,(T1) CAIN T2,(CONN) ;ONCE WE FIND A MATCHING ENTRY, JRST [ CALL RFCFRE ; DELETE IT FROM THE RFC TABLE JRST RELCN2 ] ; AND GO FINISH CLEANUP AOBJN T1,RELCN1 RELCN2: LOAD T1,CHALDX,(CONN) ;GET CONNECTION INDEX CAIL T1,MAXCON ;VALID? CHABUG(CHARBC) ;NO, COMPLAIN ABOUT IT BUT GO ON (SIGH) MOVE T2,[400000,,-1] ANDCAM T2,CHACON(T1) ;CLEAR IN USE AND CONNECTION BLOCK POINTER DEBUG,< SETZM CONMAG(CONN) > ;MAKE SURE IT'S NEVER MISTAKEN AGAIN FOR VALID CALL OKSKDP MOVEI T1,(CONN) JRST RELRES ;RELEASE STORAGE BLOCK ITSELF AND RETURN SUBTTL NVT SUPPORT SWAPCD ; ATTACH CONNECTION TO PTY (FROM .ATNVT) ; CALL: T1/ JFN OF OPENED NETWORK CONNECTION WITH CHKJFN DONE ; ; RETURNS ; +1 CANNOT ATTACH ; +2 OK. THE JFN IS RELEASED, AC 1 HAS LINE NUMBER OF ATTACHED PTY. CATNVT::MOVEI T1,ATNX2 ;ERROR CODE IF TEST SKIPS TQNE ;MUST BE OPENED FOR READING AND WRITING TQNN JRST ATPER1 MOVEI T1,ATNX3 ;RECEIVE NOT OPEN TQNN ;IS IT OPEN? JRST ATPER1 HRRZ CONN,FILCON(JFN) ;GET CONNECTION CHKCON ;VALIDATE IT IF DEBUGGING HRRZ T1,CHASTA(CONN) ;GET CONNECTION STATUS CAIN T1,.CSRFC ;RFC RECEIVED? JRST ATNVT1 CAIN T1,.CSOPN ;OPENED OK JRST ATNVT2 MOVEI T1,ATNX6 JRST ATPER1 ATNVT1: CALL SNDOPN ;ACCEPT THE RFC (WAS IN RFC-RECEIVED STATE) ATNVT2: XCTUM [HLL CONN,1] ;99 GET FLAGS IFN TNXFLG,< MOVE T1,CONN ;WHERE ROUTINE EXPECTS CONNECTION INDEX > CALL ASNCVT ;ASSIGN NVT TO THESE UNITS JRST [ MOVEI A,ATNX13 ;CAN'T, NO PTY'S JRST ATPER1 ] IFN T20FLG,< PUSH P,T2 ;SAVE ADDRESS OF DYNAMIC AREA > STOR T1,CHANVT,(CONN) ;SAVE TTY NUMBER IORI T1,.TTDES ;CONVERT PTY TO TTY DESIGNATOR UMOVEM T1,1 ;RETURN TO USER CALL CHACL4 ;RELEASE JFN STORAGE FOR WINDOWS CALL RELJFN ;RELEASE SEND JFN IFN T20FLG,< POP P,T2 ;GET BACK ADDRESS OF DYNAMIC DATA CALL ULKTTY ;UNLOCK DATA BASE > SMRETN ;RETURN SKIPPING ATPER1: CALL UNLCKF JRST MRETNE ;SAVE ERROR RETURN IN AC1 ;CLOSE THE CONNECTION ASSOCIATED WITH THIS NVT---CANNOT BLOCK (CAN BE CALLED ;WITH DEVICE LOCK LOCKED IF DETACHING MANUALLY!): REQUEST THAT THE ;CHAOS BACKGROUND FORK CLOSE IT. CVTCLZ::CHKCON ;CHECK CONN REF IF DEBUGGING MOVX T1,CF%CLS ;MARK IT AS NEEDING IORM T1,CHASTA(CONN) ; CLOSING SOMETIME SOON MOVX T1,CH%CLS ;TELL CHAOS FORK THERE'S A CLOSE REQUEST IORM T1,CHAFLG RET ;START UP OUTPUT FOR A LINE; JUST ASKS BACKGROUND FORK TO LOOK AT THIS ;TTY NEXT SCAN. ;RETURNS +1 ALWAYS. ; CONN/ CONNECTION IN QUESTION ;+++ UNUSED NOW, SINCE IT WAS TOO SLOW: THE BACKGROUND FORK FLUSHES ;+++ ALL NVT OUTPUT TO THE NET EVERY CYCLE INSTEAD OR WHEN CHAFLG GETS ;+++ SET (EG, WITH CH%TTY). CHAVSO::CHKCON ;CHECK THIS CONNECTION REF IF DEBUGGING LOAD T2,CHANVT,(CONN) ;GET NVT LINE CALL CHKCVT ;MAKE SURE IT'S TRULY A CHAOS NVT JRST CHAVSB MOVX T1,CF%TTO ;MARK THIS CONNECTION IORM T1,CHASTA(CONN) ; AS NEEDING OUTPUT ATTENTION RET ;DONE CHAVSB: CHABUG(CHAVSN) ;NO, COMPLAIN AND GET OUT RET SUBTTL TTCH7 TIME NVT INPUT PROCESSING ;CALLED FROM SCHEDULER AT TTCH7 TIME TO UNPACK CHARACTERS WAITING IN ANY ;NVT CONNECTIONS' INPUT PACKET LISTS. RESCD CHTTC7::SKIPN CHAON ;IS THE CHAOSNET UP YET? RET ;NO, NOTHING TO DO SAVEQ ;SAVE CONN, FX, Q2 IFN CHDR11,< CALL CCHKDR ;CHECK ON THE STATE OF THE DR11 PACKETS >;IFN CHDR11 STKVAR MOVEI Q2,NTTCVT+1 ;SAFETY DOWN-COUNTER MOVEM Q2,CHT7DC MOVEI Q2,CHATTW ;MARCHES THROUGH Q MOVEM Q2,CHT7IX ;SAVE IT INITIALLY CHTC70: SOSL CHT7DC ;BOUNDS CHECK THIS LOOP CAIL Q2,CHATTW+NTTCVT+1 ; AND THIS REF; BOTH WITHIN BOUNDS? CHABUG(CHT7QB) ;NOPE, SHOULDN'T HAPPEN SETO CONN, EXCH CONN,(Q2) ;PICK UP CONNECTION REF AND RESET ENTRY CAMN CONN,[-1] ;END OF Q? JRST CHTCDN ;YES, GET OUT HRRZ CONN,CONN ;CLEAR OUT LEFT HALF (UNIQUIZER) CHKCON ;VALIDATE IT IF DEBUGGING LOAD T2,CHANVT,(CONN) ;GET NVT INDEX CALL CHKCVT ;IS THIS A VALID NVT (DOUBLE CHECK)? JRST CHTC7B CALL CVTUPI ;EMPTY THIS CONNECTION'S DATA TO THE NVT'S INPUT CHTC79: AOS Q2,CHT7IX ;BUMP TO NEXT Q ENTRY JRST CHTC70 ;KEEP GOING CHTCDN: SETOM CHATTW ;DONE, CLEAR OUT QUEUE RET CHTC7B: CHABUG(CHT7IN) ;NO (INVALID NVT INDEX), COMPLAIN JRST CHTCDN ;AND GET OUT ;CALLED AT RELCON TIME TO CLEAR OUT ANY REFERENCES TO CONN IN CHATTW ;(CALLED NOSKDP, OF COURSE). CH7CLN: SAVET MOVEI T1,CHATTW ;SCAN THE QUEUE FOR ANY OCCURENCES CH7CLL: MOVE T2,(T1) ;PICK UP ENTRY CAMN T2,[-1] ;DONE? RET ;YEP, GET OUT TLZ T2,-1 ;CLEAR OUT ANY JUNK CAIE T2,(CONN) ;FOUND IT? AOJA T1,CH7CLL ;NO, KEEP LOOKING CH7CLR: MOVE T2,1(T1) ;YES, PICK UP NEXT ENTRY MOVEM T2,(T1) ;MOVE IT IN OVER THIS ONE CAMN T2,[-1] ;END OF Q? RET ;YES, GET OUT AOJA T1,CH7CLR ;NO, MOVE NEXT SWAPCD SUBTTL CHAOS NET SEQUENTIAL I/O ;NETWORK INPUT CHASQI: SOSGE FILCNT(JFN) ;ANY MORE BYTES? JRST SQI1 ;NO, MUST GO GET SOME MORE FROM NETWORK BUFFERS ILDB T1,FILBYT(JFN) RET SQI1: CALL GETINP ;PROCESS BUFFERS FROM NETWORK JRST SQIBLK ;GO BLOCK MAYBE JRST CHASQI ;AND START AGAIN ;HERE IF SHOULD BLOCK SQIBLK: HRRZ CONN,FILCON(JFN) ;GET CONNECTION BLOCK CHKCON ;VALIDATE IT IF DEBUGGING CONPTH [3] HRRZ T1,CHASTA(CONN) CAIN T1,.CSPRF ;STILL HAVE A CHANCE OF MAKING DATA? JRST INPWAT ;YES CAIE T1,.CSOPN ; ... CAIN T1,.CSRFS JRST INPWAT ;WAIT FOR INPUT BUFFERS TO APPEAR CAIN T1,.CSCLS ;JUST CLOSED NORMALLY? JRST [ HLRZ T1,CHAIBF(CONN) ;YES, ANY DATA THERE? JUMPN T1,INPWAT ;OK, GO "WAIT" FOR IT TQO ;NO, IT'S END-OF-FILE TIME CONPTH [4] RET ] TQO ;ELSE IS AN ERROR TO TRY TO READ FROM IT CONPTH [5] RET INPWAT: TQNE ;SEEN AN EOF FOR CONNECTION? JRST INPEOF ;YES, DONT GO BLOCKED THEN CONPTH [6] MOVSI T1,(CONN) HRRI T1,INPWTT ;WAIT FOR CHAOSNET INPUT IFN T20FLG,< CHAWAT: TQO ;YES, SAY NEED TO GO BLOCKED RETBAD () >;IFN T20FLG IFN TNXFLG,< CHAWAT: MOVE P,MPP MOVE B,0(P) ;GET AND DECREMENT RETURN PC SOS B HRRM B,0(P) ;BACK TO RETURN ON STACK PUSHJ P,UNLCKF ;UNLOCK JFN JSYS EDISMS ;WAIT FOR EVENT JRST MRETN ;BACK OUT TO USER >;IFN TNXFLG INPEOF: SETZ T1, ;RETURN 0 FOR INPUT BYTE RET RESCD INPWTT: TCHKCN ;IF DEBUGGING, CHECK CONNECTION HRRZ T2,CHASTA(T1) ;MAKE SURE CONNECTION STILL IN GOOD STATE CAIE T2,.CSOPN CAIN T2,.CSRFS CAIA JRST 1(T4) HLRZ T2,CHAIBF(T1) ;SEE IF ANYTHING ON INPUT BUFFER QUEUE JUMPN T2,1(T4) ;YES, UNBLOCK TO PROCESS IT JRST 0(T4) SWAPCD ;UNDO INPUT CHAUIN: TQZN ;REALLY DOING INPUT AT ALL? RET ;NO, DONE SKIPGE T1,FILCNT(JFN) SETZ T1, HRRM T1,FILBCT(JFN) ;SAVE CURRENT INPUT COUNT MOVE T1,FILBYT(JFN) MOVEM T1,FILBFI(JFN) ;AND CURRENT INPUT BYTE POINTER RET ;SETUP FOR INPUT CHAINP::SAVET ;FOR THE SAKE OF TENEX TQOE ;NOW DOING INPUT RET CALL CHAUOU ;UNDO OUTPUT HRRE T3,FILBCT(JFN) ;GET INPUT COUNT JUMPG T3,CHAIN2 ;HAVE ANY INPUT ALREADY? CALL GETINP ;NO, TRY TO GET SOME JFCL ;IGNORING LOSSAGE RET CHAIN2: MOVE T2,FILBFI(JFN) ;INPUT BYTE POINTER HRRE T1,FILBCT(JFN) ;AND COUNT CHAIN3: MOVEM T1,FILCNT(JFN) ;SETUP CURRENT COUNT ADDM T1,FILLEN(JFN) ;UPDATE LENGTH OF WHOLE MOVEM T2,FILBYT(JFN) ;AND BYTE POINTER RET ;SETUP FOR OUTPUT CHAOUP::SAVET ;FOR THE SAKE OF TENEX TQOE RET CALL CHAUIN ;UNDO INPUT SKIPN FILOBF(JFN) ;IS THERE A PACKET TO STUFF INTO YET? JRST GETOUT ;NO, GET ONE MOVE T2,FILBFO(JFN) HLRE T1,FILBCT(JFN) JRST CHAIN3 ;UNDO OUTPUT CHAUOU: TQZN RET SKIPGE T1,FILCNT(JFN) SETZ T1, HRLM T1,FILBCT(JFN) MOVE T1,FILBYT(JFN) MOVEM T1,FILBFO(JFN) RET ;GET SOME MORE INPUT FROM THE NETWORK BUFFERS; RETURN NON-SKIP IF NOTHING GOTTEN ;(EG, ERROR) GETINP: HRRZ CONN,FILCON(JFN) ;GET CONNECTION BLOCK CHKCON ;VALIDATE IT IF DEBUGGING CONPTH [7] HRRZ T3,CHASTA(CONN) CAIN T3,.CSRFC ;RFC RECEIVED? JRST SNDOPN ;YES, DOING INPUT IMPLIES ACCEPTING THE CONNECTION LOAD T3,CHABSZ,(CONN) HRRZ T1,FILWND(JFN) ;INPUT WINDOW MOVE PKT,T3 ;MAKE A BYTE POINTER TO THE WINDOW IORI T3,4400 DPB T3,[POINT 12,T1,11] MOVEI T2,44 IDIVI T2,(PKT) LSH T2,PGSFT MOVEM T1,FILBYT(JFN) SETZM FILCNT(JFN) ;RESET COUNT OF CHARS GOTTEN THIS TIME GETIN1: HLRZ PKT,CHAIBF(CONN) ;CHECK FIRST ON INPUT LIST JUMPE PKT,GETIN4 ;NO MORE, RETURN CHKPKT ;VALIDATE IF DEBUGGING PKTPTH [42] LOAD T3,CPKOP,(PKT) CAIE T3,.COCLS CAIN T3,.COLOS ;WAS THIS A LOS? JRST [ CALL GETLOS ;SET ERROR MESSAGE FROM IT CONPTH [11] JRST GETIN4 ] LOAD T3,CPKNB,(PKT) ;GET BYTE COUNT FOR THIS PACKET SUBI T2,(T3) ;DECREMENT FREE COUNT JUMPL T2,GETIN4 ;NO ROOM FOR ALL PACKETS NOW PUSH P,T1 ;SAVE BYTE POINTER CALL CHGETP ;GET THIS PACKET, DO ACKING, ETC. JRST [ ADJSP P,-1 ;FLUSH BP JRST GETIN4 ] ;OOPS, NO MORE, JUST RETURN POP P,T1 ;GET BACK BYTE POINTER JUMPE T3,GETIN3 ADDM T3,FILCNT(JFN) PUSH P,T2 MOVE T2,[POINT 8,CHPKDT(PKT)] GETIN2: ILDB T4,T2 ;MOVE THIS BUFFER OVER IDPB T4,T1 SOJG T3,GETIN2 POP P,T2 GETIN3: RCALL RELPKT,4 ;NO LONGER NEED THIS PACKET JRST GETIN1 ;TRY TO PROCESS NEXT ONE GETIN4: SKIPG T1,FILCNT(JFN) ;DID WE GET ANY? JRST [ MOVX T1,CF%EOF ;HAVE WE SEEN AN EOF PACKET? TDNE T1,CHASTA(CONN) TQO ;YES, SET EOF FOR THIS STREAM CONPTH [12] SETZ T1, ;SOMETHING VENTURED, NOTHING GAINED RET ] ADDM T1,FILLEN(JFN) ;GOT SOME, UPDATE LENGTH OF WHOLE RETSKP ;SUCCESS RETURN, WITH T1/NUMBER CHARS GOTTEN ;ROUTINE TO CALL TO GET A PACKET FROM A CONNECTION; RETURNS NON-SKIP IF ;NO PACKET THERE BY SURPRISE; THIS NEEDS TO BE LOCKED UP TO AVOID A RACE. CHGETP: CALL NOSKDP ;LOCK THIS UP MOVEI Q2,CHAIBF(CONN) CALL CHAQGF ;GET PACKET OFF LIST SINCE THERE IS ROOM JUMPE PKT,CHGETE ;NONE THERE, FAIL RETURN LOAD T1,CPKOP,(PKT) CAIE T1,.CORFC ;UNLESS READING A RFC SOS CHANBF(CONN) ;ONE LESS ON LIST CALL CHPKIA ;HANDLE ACK OF IT IF EOF OR DATA PACKET AOS (P) ;SUCCESS CHGETE: CALLRET OKSKDP ;ALL DONE IN ANY CASE RESCD ;HANDLE ACK OF DATA AND EOF PACKETS; REMEMBER WE'VE SEEN AN EOF PACKET IF SO FOR ;STREAM I/O'S SAKE. CHPKIA::SAVET ;SAVE AC'S LOAD T3,CPKOP,(PKT) ;GET OPCODE CAIE T3,.COEOF ;EOF? CAIL T3,.CODAT ;OR DATA? CAIA ;YES RET ;NOPE, FORGET IT MOVX T1,CF%EOF ;MARK THIS CONNECTION AS HAVING SEEN AN EOF CAIN T3,.COEOF IORM T1,CHASTA(CONN) ; IF WE'RE NOW LOOKING AT ONE HRRZ T1,CHASTA(CONN) ;THIS CONNECTION STILL OPEN? CAIE T1,.CSOPN RET ;NO, DON'T SEND ANY STATI PUSH P,PKT ;SAVE PKT OVER POTENTIAL CHASTO CALL LOAD T1,CPKPN,(PKT) ;GET PACKET NUMBER HRLM T1,CHAPKN(CONN) ;UPDATE LAST GIVEN TO USER CONPTH [10] CONPTH T1 ;REMEMBER, IF DEBUGGING, WHAT WE JUST SET HLRZ T2,CHAACK(CONN) ;GET LAST WE ACK'ED SUB T1,T2 SKIPGE T1 ADDI T1,200000 IMULI T1,3 ;CHECK AGAINST 1/3 WINDOW SIZE HLRZ T2,CHAWIN(CONN) CAIE T3,.COEOF ;IF EOF, OR CAML T1,T2 ; NEED ACKING, CALL CHASTO ;SEND STATUS NOW POP P,PKT RET SWAPCD ;ACCEPT AN RFC SNDOPN: HLRZ PKT,CHAIBF(CONN) ;GET HEAD OF INPUT QUEUE JUMPE PKT,SNDOP1 ;NONE THERE LOAD T1,CPKOP,(PKT) ;GET THE OPCODE CAIE T1,.CORFC ;THE RFC STILL HANGING AROUND? JRST SNDOP1 ;NO MOVEI Q2,CHAIBF(CONN) ;YES, REMOVE IT THEN CALL CHAQGF JUMPE PKT,SNDOP1 ;IF NOT THERE (?), DON'T FLUSH IT RCALL RELPKT,5 ;AND FLUSH IT SNDOP1: MOVEI T1,.CSOPN ;MAKE CONNECTION BE OPENED HRRM T1,CHASTA(CONN) CONPTH [13] MOVEI Q2,.COOPN ;OPN OPCODE JRST CHASO2 ;SEND LIKE A STS PACKET ;SEQUENTIAL OUTPUT CHASQO: PUSH P,T1 ;SAVE CHARACTER CHASQ1: SOSL FILCNT(JFN) JRST CHASQ2 SETZM FILCNT(JFN) ;DIDNT REALLY PUT IN ANOTHER CHARACTER CALL FLSOUT ;FORCE OUT THIS BUFFER JRST [POP P,(P) RET] ;ERROR RETURN CALL GETOUT ;AND GET NEW ONE JRST CHASQ1 CHASQ2: POP P,T1 IDPB T1,FILBYT(JFN) RET ;FORCE OUT THE REST OF THIS BUFFER CHASQR: MTOSND: ;I GUESS FOR NOW FLSOUT: HRRZ CONN,FILCON(JFN) CHKCON ;VALIDATE IT IF DEBUGGING CONPTH [14] HRRZ PKT,FILOBF(JFN) JUMPE PKT,RSKP ;NONE THERE NOW, FORGET IT CHKPKT ;VALIDATE PACKET IF DEBUGGING PKTPTH [43] MOVE T1,CHPMXT SUB T1,FILCNT(JFN) ;GET SIZE OF PACKET DATA STOR T1,CPKNB,(PKT) SETZM FILCNT(JFN) SETZM FILOBF(JFN) CALL SNDPKT ;SEND OFF AS A DATA PACKET TQOA RETSKP MOVEI T1,IOX5 ;ERROR RETURN RET ;GET ANOTHER OUTPUT BUFFER GETOUT: HRRZ CONN,FILCON(JFN) ;GET CONNECTION BLOCK CHKCON ;VALIDATE IT IF DEBUGGING HRRZ T1,CHASTA(CONN) ;GET STATE OF CONNECTION CAIN T1,.CSRFC ;RFC RECEIVED? CALL SNDOPN ;YES, ACCEPT CONNECTION THEN MOVEI Q2,.CODAT ;RANDOM DATA OPCODE RCALL ASGPKC,32 ;GET PACKET FOR THIS CONNECTION JRST [ MOVEI T1,^D100 DISMS CONPTH [15] IFN TNXFLG,< MOVE T1,FORKX MOVE T1,FKINT(T1) TLNN T1,(1B1) ;CHECK MANUALLY FOR INTERRUPT JRST GETOUT MOVE P,MPP ;AND UNWIND IF THERE IS ONE MOVE B,(P) SOS B HRRM B,(P) JRST MRETN] > IFN T20FLG,< JRST GETOUT] > HRRZM PKT,FILOBF(JFN) ADD PKT,[POINT 8,CHPKDT] ;MAKE BYTE POINTER TO DATA PORTION MOVEM PKT,FILBYT(JFN) MOVE T1,CHPMXT MOVEM T1,FILCNT(JFN) RET ;HANDLE A LOS PACKET, MOVE THE STRING OF THE DATA INTO THE JSB SOMEPLACE; ;RETURN "LOS RECEIVED FOR CONNECTION" ERROR CODE IN T1 FOR USE BY CALLER. GETLOS: MOVEI Q2,CHAIBF(CONN) ;GET PACKET FROM CONNECTION CALL CHAQGF JUMPE PKT,R ;NONE THERE CHKPKT LOAD T3,CPKOP,(PKT) CAIE T3,.CSCLS CAIN T3,.COLOS ;FIND THE LOS JRST GETLS1 RCALL RELPKT,6 ;I DONT THINK THERE SHOULD EVER BE ANY OF THESE JRST GETLOS GETLS1: HLRZ T2,FILCON(JFN) JUMPE T2,GETLS2 HRRZS (T2) MOVEI T1,JSBFRE CALL RELFRE ;RETURN OLD STRING TO FREE STORAGE IF ANY HRRZS FILCON(JFN) GETLS2: LOAD T2,CPKNB,(PKT) ;GET BYTE SIZE OF THIS PACKET JUMPE T2,GETLS4 ;NOTHING THERE, FORGET IT MOVEI T2,4+1+3(T2) ;PLUS ONE WORD FOR HEADER AND ONE BYTE FOR NULL LSH T2,-2 ;NUMBER OF WORDS NOINT ;UNTIL WHERE IT WILL BE REMEMBERED CALL ASGJFR JRST [ OKINT JRST GETLS4] ;CAN'T, GO CLEAN UP AND REPORT ERROR HRLM T1,FILCON(JFN) ;SAVE STRING FOR ERROR REPORTING OKINT HRLI T1,() MOVE T2,[POINT 8,CHPKDT(PKT)] LOAD T3,CPKNB,(PKT) JUMPE T3,GETLS3 ILDB T4,T2 ;MOVE OVER STRING OF DATA IDPB T4,T1 SOJG T3,.-2 GETLS3: IDPB T3,T1 ;AND A NULL FOR GOOD MEASURE GETLS4: RCALL RELPKT,7 MOVEI T1,CHAOX1 RET ;CHA: DEVICE STATUS CHASTS: IFN TNXFLG,< TEST (NN,OPNF) JRST [ SETZ T1, ;PRETEND STATE IS CLOSED IF NOT OPENED RET] > HRRZ CONN,FILCON(JFN) CHKCON ;VALIDATE IT IF DEBUGGING HRRZ T1,CHASTA(CONN) ;WILL END UP IN USER AC2 HRR T2,CHANBF(CONN) HRL T2,CHANOS(CONN) ;AC3: AVAILABLE OUTPUT WINDOW,, UMOVEM T2,3 ; NUMBER OF PKTS WAITING IN RCV END RET SUBTTL CHAOS NET MTOPRS CHAMTO: HRRZ CONN,FILCON(JFN) CHKCON ;VALIDATE IT IF DEBUGGING XCTUM [HRRZ T2,2] MOVSI T1,-NCHMTS CHAMT1: HLRZ PKT,CHAMTB(T1) CAIN PKT,(T2) JRST CHAMT2 AOBJN T1,CHAMT1 RETBAD (MTOX1) CHAMT2: HRRZ T2,CHAMTB(T1) IFN T20FLG,< JRST (T2) > IFN TNXFLG,< MOVEI T3,CHAWAT ;SUPPLY WAIT COROUTINE CALL (T2) ;CALL ROUTINE SKIPA RET MOVEM T1,LSTERR## ;SAVE FOR GETER CALL UNLCKF ;UNLOCK FILE ITERR() ;SINGLE RETURN MEANS ERROR, GIVE PSI > CHAMTB: .MOACN,,MTOACN ;SET INTERRUPT CHANNEL .MOERR,,MTOERR ;GET ERROR MESSAGE .MOSND,,MTOSND ;SEND OUT ANY BUFFERED OUTPUT .MOPKS,,MTOPKS ;SEND A SINGLE DATA PKT .MOPKR,,MTOPKR ;RECV A SINGLE DATA PKT .MOSWS,,MTOSWS ;SET WINDOW SIZE .MOOPN,,MTOOPN ;ACCEPT AN RFC .MOEOF,,MTOEOF ;SEND EOF FOR CONNECTION .MONOP,,MTONOP ;WAIT FOR DATA TO GET SENT .MOAWS,,MTOAWS ;AVAILABLE WINDOW SIZE .MOFHS,,MTOFHS ;FOREIGN HOST .MOSIZ,,MTOSIZ ;MAXIMUM SIZE OF PACKET AVAILABLE .MORWS,,MTORWS ;READ THE CURRENT WINDOW SIZES .MOUAC,,MTOUAC ;READ THE NUMBER OF UNACK'ED PKTS .MOSRT,,MTOSRT ;SET RFC TIMEOUT PERIOD IN MS IFN FRNDLY,< .MOFRH,,MTOFRH ;CHECK FOR FRIENDLY HOST > NCHMTS==.-CHAMTB IFN FRNDLY,< FRHTAB: FRENDS FRHTBL==.-FRHTAB ;CHECK HOST FOR JFN FOR BEING FRIENDLY MTOFRH: XCTUM [SKIPN T4,3] ;GET HOST IF SPEC'ED LOAD T4,CHAHST,(CONN) ;ELSE GET FOREIGN HOST FOR CONN MOVSI T3,-FRHTBL MTOFR2: MOVE T1,FRHTAB(T3) ;GET FRIENDLY HOST NAME SUBI T1,1 ;STANDARDIZE POINTER CALL HSTNAM ;GET NAME FOR HOST SETZ T1, CAMN T1,T4 ;SAME HOST? JRST MTOFR1 ;YES, A WINNER AOBJN T3,MTOFR2 TDZA T3,T3 MTOFR1: SETO T3, UMOVEM T3,3 ;RETURN TO USER RETSKP > ;SET TIMEOUT PERIOD (IN MS) FOR RFC WAITING VIS A VIS THIS CONNECTION MTOSRT: UMOVE T3,3 ;PICK UP TIMEOUT STOR T3,CHATRF,(CONN) ;SET IT IN (MAX ~256 SECS SINCE ONLY HALFWD) RETSKP ;NOTE: BY "UNACK'ED" PACKETS, I MEAN UNDELIVERED, IN DISTINCTION FROM UNRECEIPTED ;PACKETS. THIS ISN'T CONSISTENT WITH OTHER COMMENTS IN THIS FILE; SIGH. MTOUAC: CALL NOSKDP ;LOCK OUT WINDOW HACKING FOR A JIFFY HRRZ T3,CHAWIN(CONN) ;GET TRANSMIT WINDOW SUB T3,CHANOS(CONN) ; SUBTRACT OUT AVAILABLE WINDOW CALL OKSKDP ;UNLOCK UMOVEM T3,3 ;RETURN THIS AS NUMBER OF UNACKNOWLEDGED PACKETS RETSKP MTORWS: SKIPA T3,CHAWIN(CONN) ;GET CURRENT RECEIVE,,TRANSMIT WINDOW SETTINGS MTOSIZ: MOVE T3,CHPMXT ;GET MAXIMUM SIZE IN BYTES OF PACKET WE CAN HANDLE UMOVEM T3,3 RETSKP ;ASSIGN INTERRUPT CHANNELS FOR STATE CHANGE NOTIFICATION MTOACN: XCTUM [HRRZ T3,3] STOR T3,CHAICN,(CONN) XCTUM [HLRZ T3,3] STOR T3,CHAOCN,(CONN) MOVE T3,FORKX ;JUST IN CASE SOME OTHER FORK OPENED THIS UP STOR T3,CHAFRK,(CONN) RETSKP ;GET AN ERROR STRING FROM A LOS OR CLS MTOERR: HLRZ T2,FILCON(JFN) ;GET ERROR BYTE POINTER JUMPE T2,[RETBAD (CHAOX4)] HRLI T2,() UMOVE T3,3 TLC T3,-1 TLCN T3,-1 HRLI T3,() ;STANDARDIZE BYTE POINTER FROM USER MTOER1: ILDB T1,T2 JUMPE T1,MTOER2 XCTBU [IDPB T1,T3] JRST MTOER1 MTOER2: UMOVEM T3,3 ;RETURN USER UPDATED BYTE POINTER XCTBU [IDPB T1,3] ;AND APPEND A NULL FOR GOOD MEASURE RETSKP ;SET RECEIVE WINDOW SIZE MTOSWS: UMOVE T1,3 ;GET NEW SIZE CAMLE T1,MXRWIN ;RANGE CHECK IT MOVE T1,MXRWIN SKIPG T1 ;IS IT UNREASONABLE? MOVE T1,1 ;YES, LESS THAN 1 IS USELESS HRLM T1,CHAWIN(CONN) AOS (P) ;CAN'T FAIL FROM NOW ON HRRZ T1,CHASTA(CONN) ;GET STATE NOW CAIE T1,.CSOPN ;OPEN CONNECTION THERE? RET ;NO, DONT TRY TO SEND ANYTHING JRST CHASO1 ;YES, SEND A STS RIGHT AWAY SO IT TAKES EFFECT ;RETURN AVAILABLE WINDOW SIZE FOR SENDING MTOAWS: MOVE T3,CHANOS(CONN) UMOVEM T3,3 RETSKP MTOFHS: LOAD T3,CHAHST,(CONN) ;GET FOREIGN HOST UMOVEM T3,3 ;+++SHOULD ADD IN NETWORK NUMBER, I GUESS RETSKP ;SEND A SINGLE DATA PACKET MTOPKS: IFN KLFLG!SMFLG,< XCTBU [LOAD Q2,CPKOP,(3)] ;GET OPCODE > IFN F3FLG,< UMOVE T3,3 HRLI T3,() XCTBU [LDB Q2,T3] > HRRZ T3,CHASTA(CONN) ;AND CONNECTION STATE CAIN T3,.CSPRF ;IN PERMANENT-RFC-SENT STATE? CAIE Q2,.CORFC ; AND TRYING TO SEND A RFC? CAIA ;NO JRST [ CALL MTPKS3 ;YES, LET HER SEND IT; SET UP THE PACKET RET ;FAILED; MIMIC SETZ T1, ;SEND OFF, BLOCKING (ON THE FE) IS OK CALL SNDPK0 RETSKP ] ;SUCCESS CAIN T3,.CSOPN ;CONNECTION OPEN? JRST MTPKS1 ;YES, GO SEND THE PACKET AS DATA CAIE T3,.CSRFC ;RFC RECEIVED? RETBAD(CHAOX2) ;NO, NOT IN THE RIGHT STATE CAIE Q2,.COANS ;LET USER HAVE SIMPLE CONNECTIONS CAIN Q2,.COCLS ;OR SPECIFY A REASON FOR REFUSAL JRST MTPKS2 PUSH P,Q2 ;SAVE OPCODE CALL SNDOPN ;DOING OUTPUT IMPLIES ACCEPTING THE CONNECTION POP P,Q2 MTPKS1: CAIN Q2,.COEOF ;SENDING AN EOF? JRST MTOEOF ;YES, HANDLE IT CANONICALLY OUR WAY CAIN Q2,.COCLS ;SPECIFYING REASON FOR FLUSHING? JRST MTPKS2 CAIGE Q2,.CODAT MOVEI Q2,.CODAT ;MAKE IT LEGAL DATA OPCODE CALL MTPKS3 ;SETUP THE PACKET RET ;ERROR JRST SNDPKT ;GO SEND IT OFF MTPKS2: CALL MTPKS3 ;SETUP THE ANS OR CLS PACKET RET ;FAILED SETZ T1, CALL SNDPK1 ;SEND IT OFF, BLOCKING OK CALL CHACL4 ;FLUSH DATA, ETC. MOVEI T1,.CSCLS ;NOW CLOSED HRRM T1,CHASTA(CONN) RETSKP MTPKS3: IFN KLFLG!SMFLG,< XCTBU [LOAD T1,CPKNB,(3)] ;GET NUMBER OF BYTES > IFN F3FLG,< UMOVE T3,3 HRLI T3,() XCTBU [LDB T1,T3] > CAMLE T1,CHPMXT RETBAD(CHAOX3) PUSH P,T1 ADDI T1,3 ;ROUND UP LSH T1,-2 ;INTO WORDS PUSH P,T1 ;SAVE FOR LATER RCALL ASGPK1,33 ;GET A PACKET FROM LENGTH IN 1 AND OPCODE IN Q2 JRST [ ADJSP P,-2 RETBAD(MONX01) ] ;FAILED, NOT ENOUGH ROOM POP P,T1 ;WORD COUNT XCTUM [HRRZ T2,3] ;ADDR IN USER SPACE OF BUFFER ADDI T2,CHPKDT XMOVEI T3,CHPKDT(PKT) CALL BLTUM ;MOVE IT OVER POP P,T1 STOR T1,CPKNB,(PKT) ;SET UP BYTE COUNT RETSKP ;PACKET ALL SET UP NOW ;GIVE THE USER THE NEXT PACKET MTOPKR: HRRZ T3,CHASTA(CONN) CAMN CONN,CHRFHC ;IS THIS THE DISTINGUISHED RFC HANDLER? JRST MTOPKP ;YES, GO GIVE IT ANY UNHANDLED RFCS HLRZ PKT,CHAIBF(CONN) ;LOOK AT FIRST ON INPUT QUEUE JUMPE PKT,SQIBLK ;NONE THERE, WAIT FOR ONE TO APPEAR CHKPKT ;CHECK THIS IF DEBUGGING, BEFORE USING IT PKTPTH [44] CALL CHGETP ;GET THIS PACKET JRST SQIBLK ;OUCH, NOTHING THERE NOW, GO WAIT AGAIN MTOPR1: LOAD T1,CPKNB,(PKT) ;GET BYTE COUNT ADDI T1,3+CHPKDT*4 LSH T1,-2 ;INTO WORDS MOVEI T2,(PKT) XCTUM [HRRZ T3,3] ;DEST CALL BLTMU ;MOVE INTO USER SPACE RCALL RELPKT,10 ;RID OF THIS PACKET RETSKP ;HERE TO HANDLE A PACKET-READ REQUEST FROM THE DISTINGUISHED RFC HANDLER: ;HAND IT THE NEXT PACKET ON ITS INPUT LIST, WHICH IS A COPY OF AN UNHANDLED ;RFC, OR WAIT TILL SOME APPEAR IF NECESSARY. MTOPKP: SKIPN CHAIBF(CONN) ;ANYTHING IN THE INPUT QUEUE? JRST MTOPPW ;NO, GO WAIT FOR SOMETHING TO APPEAR MOVEI Q2,CHAIBF(CONN) ;YES, PULL OF FIRST PACKET CALL CHAQGF JUMPE PKT,MTOPPW ;OOPS, NOTHING THERE; GO WAIT FOR WORK SOS CHANBF(CONN) ;NOTE WE'VE TAKE THIS OFF THE INPUT LIST CHKPKT ;CHECK IT IF DEBUGGING PKTPTH [45] JRST MTOPR1 ;ELSE, GIVE IT TO THE REQUESTING RFC HANDLER FORK MTOPPW: MOVEI T1,MTOPWT ;WAIT FOR SOMETHING TO APPEAR HRLI T1,(CONN) ; ON THIS CONNECTION JRST CHAWAT RESCD MTOPWT: TCHKCN SKIPN CHAIBF(T1) ;ANY NEW PACKETS FOR US TO LOOK AT? JRST 0(T4) ;NO, KEEP WAITING JRST 1(T4) ;YES, GO GET 'EM SWAPCD ;ACCEPT A CONNECTION EXPLICITY MTOOPN: AOS (P) ;WILL SKIP RETURN JRST SNDOPN ;ACCEPT THE RFC ;SEND AN EOF PACKET ON A CONNECTION MTOEOF: CALL FLSOUT ;SEND ANY BUFFERED STREAM OUTPUT JFCL MOVEI Q2,.COEOF ;SEND AN EOF RCALL ASGPK0,34 ;GET A PACKET FOR CONNECTION RETBAD(MONX01) SETZRO CPKNB,(PKT) ;ZERO BYTE COUNT JRST SNDPKT ;AND GO SEND IT OFF ;NOP: FLUSH ANY OUTPUT AND WAIT FOR IT TO GET SENT MTONOP: PUSH P,T3 ;SAVE BLOCK PATH SUPPLIED BY .MTOPR CALL FLSOUT ;SEND ANY BUFFERED OUTPUT JFCL HRRZ T2,CHAWIN(CONN) ;PICK UP CURRENT XMIT WINDOW CAMG T2,CHANOS(CONN) ;SEE IF STILL THINGS TO BE ACK'ED JRST [ ADJSP P,-1 ;NO, GET OUT RETSKP ] MOVSI T1,(CONN) ;WAIT FOR EVERYTHING TO GET ACKNOWLEDGED HRRI T1,CLSWAT POP P,T3 ;USE BLOCK PATH SUPPLIED BY .MTOPR JRST (T3) SUBTTL LOCAL ROUTING FORK CHALRF: IFN TNXFLG,< MOVSI 1,UMODF ;FAKE UP SLOW JSYS ENTRY MOVEM 1,FPC ; .. >;IFN TNXFLG MCENTR ;START HERE: ENTER MONITOR CONTEXT MOVEI T1,1 ;WE NEED PRIORITY, STAY IN HIGHEST Q MOVEM T1,JOBBIT MOVE T1,TODCLK ;INIT BACKGROUND FORK WATCHDOG TIMER ADDI T1,^D<5*1000> ;(GIVE IT SOME TIME TO GET GOING) MOVEM T1,CHABFT CHALRL: CALL CHALCR ;DO SOME ROUTING IF ANY TO DO MOVE T1,TODCLK ADDI T1,^D5000 ;RESET OUR WAKEUP TIMER MOVEM T1,CHALRW MOVEI T1,CHLTST ;WAIT FOR SOME MORE WORK HDISMS (^D500) ;TRY TO STAY AROUND IN BALSET FOR SOME TIME JRST CHALRL RESCD CHLTST: MOVE T1,CHALRW ;TIME TO WAKE UP? SKIPN CHQLCL ;IF ANY WORK WAITING FOR US CAMG T1,TODCLK ; OR IF TIME IS UP JRST 1(T4) ; UNBLOCK JRST 0(T4) ;NOTHING TO DO YET SWAPCD ;DO SOME MAIN-BACKGROUND-FORK AND NFE-11 WEDGEDNESS CHECKING EVERY SO OFTEN ;THEN DO ANY LOCAL ROUTING THAT NEEDS BE DONE. CHALCR: MOVE T2,CHABFW ;WHERE THE BACKGROUND FORK IS, MOVE T3,CHATIM ; WHEN IT THINKS IT SHOULD RUN NEXT, MOVE T4,CHAFLG ; WHAT ITS REQUESTS ARE, MOVE Q2,TODCLK ; AND WHAT TODCLK IS NOW IFN DTEFLG,< MOVE T1,Q2 ;GET NOW SUB T1,CHABFT ;FIND OUT WHEN THE MAIN BACKGROUND FORK LAST CYCLED CAILE T1,^D<5*1000> ;IF MORE THAN A FEW SECONDS, JRST CHALCB CHALC0: MOVE T1,TODCLK ;GET NOW SKIPE T2,CHNPWT ;FIGURE OUT WHEN WE NEED TO CHECK FOR 11 WEDGEDNESS JRST CHLTS1 ;INITIALIZE FIRST TIME THROUGH MOVE T2,T1 ADDI T2,^D<5*1000> MOVEM T2,CHNPWT SETZM CHNPOW ;AND ASK TO SEE CHNPO1 DROP BELOW EMPTY CHLTS1: CAML T2,T1 ;TIME'S UP? JRST CHLTS3 ;NO, DON'T CHECK NOW ADDI T1,^D<5*1000> MOVEM T1,CHNPWT ;YES, UPDATE TIME OF NEXT CHECK SKIPGE CHNPO1 ;HOW'S THE -11 QUOTA DOING? JRST CHLTS2 ;IT'S OK SKIPG CHNPOW ;NO ROOM, HAS ANYONE SEEN ROOM IN PAST FEW SECS? SKIPN CHAON ;-11 STILL UP? CAIA ;YES OR NO CHABUG(CHA11S) ;NO, COMPLAIN ABOUT IT CHLTS2: SETZM CHNPOW ;IN ANY CASE, ASK TO SEE IT DROP BELOW EMPTY AGAIN CHLTS3: >;IFN DTEFLG SKIPN CHQLCL ;IF LOCAL-Q IS NON-EMPTY, HANDLE IT RET CHSLC1: CALL NOSKDP ;LOCK OUT OTHER DIDDLERS OF THE LOCAL ROUTING Q DEBUG,< MOVEI Q2,CHQLCL ;CHECK THIS QUEUE HEADER CALL CHAQCK JFCL ;ANY PROBLEM ALREADY REPORTED >;DEBUG HLRZ PKT,CHQLCL ;GET A PACKET FROM LOCAL Q JUMPE PKT,OKSKDP ;NO MORE, GET OUT AFTER UNLOCKING THINGS CHKPKT ;CHECK IT IF DEBUGGING PKTPTH [46] HLRZ T1,PKTLNK(PKT) ;PICK UP LOCAL-Q LINK FROM THIS PACKET CAIN T1,1 ;SOME PHONY XMIT-ACTIVE FLAG? CAIE T1,-1 ; OR NON-LINKED MARKER? CAIA ;NO AND NO CHABUG(CHSLCR) ;YES, COMPLAIN (JUST IN CASE) HRROS PKTLNK(PKT) ;MARK AS NOT ON LOCAL-Q LIST ANY MORE HRLM T1,CHQLCL ;MAKE NEXT THE NEW FIRST SKIPN T1 ;WAS IT THE LAST? SETZM CHQLCL ;YES, Q IS NOW EMPTY PUSH P,PKT ;SAVE THIS PACKET OVER CHIPKT CALL XMOVEI T1, ;REMEMBER OUR SECTION JUMPE T1,[CALL CHIPKT ;ALREADY SECTION 0, DON'T DO ANY JRST CHSLC2] ; SWITCHING SE0ENT ;CHIPKT WANTS TO RUN IN SECTION 0 CALL CHIPKT ;HERE'S A PACKET FROM MYSELF SE1ENT ;BACK TO 1 IF WE WERE ALREADY THERE CHSLC2: POP P,PKT ;GET BACK ORIGINAL PACKET RCALL RELPKM,11 ;GET RID OF IT IF IT'S NOT ON OTHER LISTS CALL OKSKDP ;UNLOCK THINGS JRST CHSLC1 ;BACK FOR MORE IFN DTEFLG,< CHALCB: CHABUG(CHATBF,<,,,>) MOVE T1,TODCLK ;COMPLAIN AND UPDATE SO WE DON'T BARF TOO OFTEN MOVEM T1,CHABFT JRST CHALC0 >;IFN DTEFLG SUBTTL CHAOS NETWORK FORK DEFINE WCALL (R) < ;;;FOR DEBUGGING: NOTE WHAT WE'RE DOING DEBUG,< MOVEI T1,R MOVEM T1,CHABFW CALL R >;DEBUG NODEB,< CALL R > > CHSFRK: IFN TNXFLG,< MOVSI 1,UMODF ;FAKE UP SLOW JSYS ENTRY MOVEM 1,FPC ; .. >;IFN TNXFLG MCENTR MOVE T1,FORKX ;SAVE OUR FORK INDEX MOVEM T1,CHAFHN MOVEI T1,1 ;SAY WE SHOULD ALWAYS STAY IN HIGHEST-PRIORITY MOVEM T1,JOBBIT ; QUEUE MOVE T1,CHAON MOVEM T1,CHAONL ;REMEMBER LAST VALUE OF CHAON SETZM CHNPWT ;INITIALIZE -11 WEDGENESS TIMER SETZM CHATIM ;CLEAR OUR CYCLE CLOCKS: BASIC CYCLE, SETZM CHATM1 ; TIMEOUT CYCLE SETZM CHATM2 ; RFC CHECK CYCLE SETZM CHNGTM ; NEGOTIATION TIMEOUTS FOR NVT'S CALL CHSINI ;BUILD OUR HOST TABLE FROM HOSTS2 NOW ;BASIC CYCLE: PROCESS REQUESTS, AND HANDLE ALARMS FOR TIMEOUTS, ETC. ;EACH ROUTINE WORRIES ABOUT SEEING IF IT'S TIME TO HANDLE ITS PARTICULAR ;TASK, AND, IF SO, SETTING UP THE TIME TO RUN NEXT TIME. CHIFRF: MOVE T1,TODCLK ;UPDATE WHEN WE LAST RAN OUR BASIC CYCLE MOVEM T1,CHABFT SETZ T1, ;NOW, PICK UP FLAGS EXCH T1,CHAFLG ; AND RESET THEM MOVEM T1,CHAPFG ;SET LAST FLAG VALUE (WHAT WE USE BELOW) SETZM CHAONC ;ASSUME NET HASN'T CHANGED ON US MOVE T1,CHAON CAME T1,CHAONL ;ANY CHANGE IN NET STATUS? JRST [ SETO T2, ;NO, ASSUME IT JUST WENT DOWN SKIPE CHAON ;DID IT? MOVEI T2,1 ;NO, JUST CAME UP MOVEM T2,CHAONC ;TELL WHAT HAPPENED JRST .+1 ] MOVEM T1,CHAONL ;REMEMBER WHAT WE JUST SAW FOR NEXT TIME THROUGH WCALL CHFCC ;DO SOME CONSISTENCY CHECKS WCALL CHATTS ;HANDLE ANY NVTS THAT NEED IT WCALL CHFCNS ;UPDATE BASIC CYCLE CLOCKS, SCAN CONNECTIONS WCALL CHFRFC ;DO ANY RFC HANDLING WCALL CHANEG ;DO ANY NVT NEGOTIATION TIMEOUTS MOVE T1,CHATIM SKIPN CHAFLG ;IF ANY FLAGS ARE SET AGAIN CAMG T1,TODCLK ; OR IF BASIC CYCLE ALARM TIME IS HERE ALREADY JRST CHIFRF ; GO HANDLE IT DEBUG,< MOVEI T1,. ;NOTE WE'RE WAITING HERE MOVEM T1,CHABFW ; FOR DEBUGGING PURPOSES >;DEBUG MOVEI T1,CHFTST ;NO, WAIT UNTIL OUR TIME HDISMS (^D500) ; COMES OR UNTIL SOMETHING HAPPENS WE CARE ABOUT JRST CHIFRF ; (THE HDISMS IS TO STAY IN THE BALANCE SET) RESCD CHFTST: MOVE T1,CHATIM ;GET TIME FOR NEXT FULL FORK RUN SKIPN CHAFLG ;IF ANY REQUESTS FOR WORK, OR CAMG T1,TODCLK ; IF TIME IS UP JRST 1(T4) ;UNBLOCK JRST 0(T4) ;ELSE, NOTHING TO DO SWAPCD ;UPDATE BASIC CYCLE CLOCKS (RETRANSMISSION AND TIMEOUT CLOCKS) AND ;DO A FULL CONNECTION SCAN FOR VARIOUS KINDS OF LOVING CARE. ;(NOTE: DON'T DISTURB BASIC ORDER HERE UNLESS YOU UNDERSTAND THE IMPLICATIONS) CHFCNS: SETZM CHATMA ;ALARMS HAVEN'T GONE OFF YET SETZM CHAT1A MOVE T1,TODCLK ;GET "NOW" SKIPL CHAONC ;IF NET HAS JUST GONE DOWN, OR IF IT'S CAMLE T1,CHATIM ; TIME TO SET OFF THE BASIC CYCLE TIME ALARM CAIA ;THEN DO SO JRST CHFCSS ;NO, MUST JUST BE SOME REQUEST TO PROCESS SETOM CHATMA ;MARK OUR BASIC-CYCLE ALARM AS BEING TRIPPED ADDI T1,^D500 ;TRY TO LOOP THRU EVERY 500 MS MOVEM T1,CHATIM ;THIS IS OUR NEXT TARGET WAKEUP TIME SUBI T1,^D500 ;GET BACK TODCLK WITHOUT POTENTIAL CHANGE CAMG T1,CHATM1 ;TIME FOR TIMEOUT CYCLE TOO? JRST CHFCSS ;NO SETOM CHAT1A ;YES, TURN ON TIMEOUT CYCLE ALARM ADDI T1,^D<5*1000> ;REMEMBER WHEN NEXT TIMEOUT CYCLE IS DUE MOVEM T1,CHATM1 CHFCSS: MOVE T1,CHAPFG ;GET POSSIBLE LIST OF KINDS OF WORK AHEAD OF US SKIPN CHATMA ;IF NO BASIC-CYCLE WORK TO DO TXNE T1,CH%IIN!CH%OIN!CH%DIN!CH%CLS!CH%STS ; AND IF NO PER-CONN REQUESTS CAIA RET ;JUST GET OUT MOVSI F1,-MAXCON ;ELSE, SCAN ALL CONNECTIONS ;SCAN LOOP CHFCSL: SKIPL CONN,CHACON(F1) ;IS THIS IN USE? JRST CHFCSE ;NO, SKIP IT HRRZS CONN ;CLEAR OUT UNIQUIZER (FOR NON-ZERO SECTIONS) CHKCON ;VALIDATE CONN IF DEBUGGING ;RETRANSMIT EVERY BASIC CYCLE SKIPE CHATMA ;DID THE BASIC CYCLE ALARM GO OFF? CALL CHARTR ;YES, TRY TO RETRANSMIT STUFF FROM THIS CONNECTION ;TIMEOUT IDLE CONNECTIONS (AND HANDLE NET GOING DOWN CLEANLY) SKIPL CHAONC ;DID THE NET GO DOWN RECENTLY SKIPE CHAT1A ;OR IS IT TIME FOR A TIMEOUT CYCLE? CAIA ;YES JRST CHIF21 ;NO, TRY NEXT THEORY HRRZ T2,CHASTA(CONN) ;GET STATE OF CONNECTION CAIE T2,.CSRFS ;RFC-SENT STATE? JRST CHIF19 ;NO, CHECK FURTHER LOAD T2,CHATRF,(CONN) ;YES, PICK UP RFC TIMEOUT JRST CHIF9A ; AND GO JOIN TIMEOUT TEST CHIF19: CAIE T2,.CSOPN ;OPENED NOW? JRST CHIF21 ;NO, SKIP THIS ONE MOVX T2,^D<90*1000> ;YES, USE OPEN CONNECTION TIMEOUT LIMIT CHIF9A: MOVE T1,TODCLK SUB T1,CHAITM(CONN) ;GET TIME SINCE LAST ACTIVITY ON THIS CONNECTION SKIPL CHAONC ;DID THE NET JUST GO DOWN, OR HAS IT BEEN CAML T1,T2 ; MORE THAN OUR LIMIT? CAIA ;YES OR YES JRST CHIF20 ;NO, GO ON MOVEI Q2,.CSINC ;INCOMPLETE TRANSMISSION: CONNECTION IS LOST CALL CHAINT ;POSSIBLY NOTIFY SOMEONE OF CONNECTION STATE CHANGE JUMPN CONN,CHIF21 ;IF STILL HAVE CONNECTION REF, TRY SOME MORE SKIPL CONN,CHACON(F1) ;ELSE, GET BACK CONNECTION JRST CHFCSE ; (NO CONNECTION ENTRY??? SKIP REST, THEN) HRRZS CONN ;CLEAR OUT UNIQUIZER JRST CHIF21 ;AND TRY NEXT THEORY ;REQUEST STATUS FOR DELINQUENT CONNECTIONS CHIF20: HRRZ T2,CHASTA(CONN) ;STILL OPEN? CAIE T2,.CSOPN JRST CHIF21 ;NO, SKIP IT MOVEI Q2,.COSNS ;WILL WANT A SNS PACKET IF LOSING HRRZ T2,CHAACK(CONN) HRRZ T3,CHAPKN(CONN) CAMN T2,T3 ;OUTSTANDING PACKETS? CAIL T1,^D<60*1000> ;NO, NOTHING IN MORE THAN A MINUTE? CAIA JRST CHIF21 ;NOTHING TO DO HERE RCALL ASGPK0,35 ;YES, GET A PACKET WITHOUT DATA JRST CHIF21 ;NO PACKET AVAILABLE SETO T1, CALL SNDPK0 ;SEND OFF PACKET, BUT NOT IF REQUIRES BLOCKING SKIPE T1 AOS CHNSNS ;ONE MORE SNS SENT IF IT GOT OUT CHIF21: ;PARANOIC CHECKING, THEN NVT-UNWEDGING IF NECESSARY LOAD T2,CHANVT,(CONN) ;GET NVT INDEX, IF ANY MOVE T1,CHASTA(CONN) ;ALSO PICK THIS UP FOR EXTRA INFO SKIPN T2 ;IS THERE ANYTHING THERE? JRST CHIF22 ;NO CALL CHKCVT ;YES, IS THIS A CVT? CHABUG(CHANCV,<,>) ;NO, COMPLAIN FOR KICKS CHIF22: ;CHECK STATUS REQUEST MOVX T1,CF%STS ;NEED STATUS DONE? TDNE T1,CHASTA(CONN) CALL CHASO1 ;YES, SEND THAT OUT ;CHECK INTERRUPT REQUESTS MOVX T1,CF%IIN ;INPUT INTERRUPT REQUESTED? TDNN T1,CHASTA(CONN) JRST CHIF11 ;NO ANDCAM T1,CHASTA(CONN) ;YES, CLEAR REQUEST LOAD T1,CHAICN,(CONN) ;GET INTERRUPT CHANNEL LOAD T2,CHAFRK,(CONN) ;AND OWNING FORK CAIGE T1,^D36 ;HAVE A VALID CHANNEL? CALL PSIRQ ;YES, INTERRUPT THE FORK CHIF11: MOVX T1,CF%OIN ;OUTPUT INTERRUPT? TDNN T1,CHASTA(CONN) JRST CHIF10 ;NO ANDCAM T1,CHASTA(CONN) ;YES, CLEAR REQUEST LOAD T1,CHAOCN,(CONN) LOAD T2,CHAFRK,(CONN) CAIGE T1,^D36 CALL PSIRQ CHIF10: MOVX T1,CF%DIN ;MARKED FOR DETACHMENT? TDNN T1,CHASTA(CONN) JRST CHIF12 ;NO ANDCAM T1,CHASTA(CONN) ;CLEAR REQUEST LOAD T2,CHANVT,(CONN) ;YES, DETACH NVT THEN CALL DETCVT ; (THIS REQUESTS A CLOSE; HANDLED BELOW) JFCL ;IGNORE ANY FAILURE CHIF12: ;HANDLE CLOSE REQUESTS FOR NVTS MOVX T1,CF%CLS ;DID SOMEONE REQUEST A FAST CLOSE? TDNN T1,CHASTA(CONN) JRST CHRDC9 ;NOT HERE, TRY NEXT THEORY LOAD T2,CHANVT,(CONN) ;GET NVT NUMBER CALL CHKCVT ;IS IT AN NVT? CHABUG(CHAMCR) ;NOPE, MISBEGOTTEN CLOSE REQUEST: NOTE IT HRRZ T1,CHASTA(CONN) ;GET CURRENT STATE CAIE T1,.CSOPN ;STILL OPEN? JRST CHRDC8 ;NO LONGER IN USEFUL STATE, GET RID OF IT MOVEI Q2,.COCLS ;SEND A CLS RCALL ASGPK0,36 JRST CHRDC8 ;CAN'T, BE RUDE AND FORGET ABOUT THE CONNECTION SETO T1, CALL SNDPK0 ;SHIP CLS OFF, BUT NOT IF IT REQUIRES BLOCKING CHRDC8: CALL RELCON ;WE CAN THROW OUT THIS CONNECTION NOW JRST CHFCSE ;AND GO ON TO NEXT; CAN'T HELP ANY MORE HERE ;GET RID OF DEAD NVTS HERE CHRDC9: HRRZ T1,CHASTA(CONN) ;GET CONNECTION STATE CAIN T1,.CSLOS ;LOSING? JRST CHRDCO ;YES, GET RID OF IT CAIE T1,.CSINC ;INCOMPLETE? CAIN T1,.CSCLS ; OR CLOSED? CAIA ;YES JRST CHFDC0 ;NO, CAN'T BE WHAT WE'RE LOOKING FOR CHRDCO: MOVE T1,TODCLK ;GET TIME SINCE LAST ACTIVITY ON THIS CONN SUB T1,CHAITM(CONN) CAIG T1,^D<60*1000> ;MORE THAN A MINUTE SINCE ANY ACTIVITY? JRST CHFDC0 ;NO, FORGET IT LOAD T2,CHANVT,(CONN) ;YES, GET POTENTIAL NVT INDEX FROM THIS CONNECTION CALL CHKCVT ;IS IT A CHAOS NVT? JRST CHFDC0 ;NO, DONE CALL RELCON ;YES, GET RID OF THIS CONNECTION CHABUG(CHADNV) ;AND TELL ABOUT THIS DEAD NVT JRST CHFCSE ;NOTHING MORE TO DO WITH THIS CONNECTION CHFDC0: CHFCSE: AOBJN F1,CHFCSL ;LOOP OVER ALL CONNECTIONS RET ;DONE ;TRY MATCHING UP INCOMING RFC'S WITH LSN'S; IF NO MATCH, PUT A COPY ;ON THE DISTINGUISHED RFC HANDLER'S INPUT QUEUE FOR IT TO WORRY ABOUT. CHFRFC: MOVX T1,CH%RFC ;ANY WORK FOR US TO DO? TDNE T1,CHAPFG JRST CHIF29 ;YES, GO TO IT MOVE T1,TODCLK ;NO, CAMG T1,CHATM2 ; TIME TO DO RFC CHECKS PERIODICALLY? RET ;NO, THAT'S IT ADDI T1,^D<5*1000> ;YES, REMEMBER WHEN TO MAKE NEXT CHECK MOVEM T1,CHATM2 CHIF29: SETZ F1, ;WHAT WE LAST SAW CHIF30: MOVEI Q2,CHQRFC ;GET RFC LIST CALL NOSKDP ;PREVENT INTERRUPT CODE FROM LOOKING CALL CHAQGF ;GET FIRST PKT MOVEM PKT,CHQRFP ;TELL INTERRUPT LEVEL WE OWN THIS PACKET CALL OKSKDP ;GET INTERRUPTS BACK JUMPE PKT,R ;Q WAS EMPTY CAIN F1,(PKT) ;IS THIS AS FAR AS WE GO ON Q? JRST [ CALL NOSKDP ;YES, LOCK UP SETZM CHQRFP ; AND CLEAR OUT THIS PACKET CALL CHAQPF ; PUT PACKET BACK CALLRET OKSKDP ] ;UNLOCK AND LEAVE MOVEI T2,CHPKDT(PKT) HRLI T2,() ;MAKE BYTE POINTER TO CONNECTION NAME MOVE T3,T2 ILDB T4,T3 ;LOOK FOR A SPACE IN IT CAIE T4," " JUMPN T4,.-2 ;NOTE THAT CONTACT NAME WAS MADE ASCIZ MOVEI T1,0 DPB T1,T3 ;PUT IN A NULL THERE JUST IN CASE PUSH P,T3 ;SAVE WHERE TO RESTORE STRING PUSH P,T2 ;SAVE REF TO START OF STRING HRROI T1,[ASCIZ /STATUS/] ;REQUEST FOR STATUS? STCMP JUMPE T1,[ADJSP P,-2 ;YES, FLUSH TEMPS JRST CHIRFS] ; AND HANDLE THAT OURSELVES POP P,T2 ;GET BACK ASCIZ REF MOVEI T1,RFCTAB TBLUK POP P,T3 DPB T4,T3 ;PUT BACK IN THE SPACE OR NULL TXNE T2,TL%EXM ;MATCHES? JRST CHIF33 ;YES, INTRODUCE THEM MOVE T1,TODCLK ;NO, SKIPN T2,PKTTIM(PKT) ; IS THIS THE FIRST TIME FOR THIS PACKET? JRST CHIF37 ;YES, SEE IF SHOULD START UP A SERVER SUB T1,T2 ;NO, SEE WHEN THIS WENT ONTO THE QUEUE CAIG T1,^D<30*1000> ;BEEN AROUND A REASONABLE AMOUNT OF TIME? JRST CHIF35 ;NO, OK PUSH P,PKT ;YES, DEBUG,< DMOVE T1,CHPKDT(PKT) ;NOW, TELL ABOUT THIS UNHANDLED RFC LOAD T3,CPKNB,(PKT) ;TELL ITS LENGTH CHABUG(CHAUHR,<,,>) >;DEBUG MOVEI T2,[ASCIZ /Timeout: no such server at this site/] CHIF3A: CALL CHALS2 ; SEND A CLS TO IT CHIF3B: POP P,PKT IFE SMFLG,< ;ON KS10, WE'VE ALREADY RECYCLED THE COPY IF ANY RCALL RELPKT,12 ;FREE THIS PKT (WHAT WAS SENT WAS COPY) >;IFE SMFLG, JRST CHIF30 CHIF37: MOVEM T1,PKTTIM(PKT) ;FIRST UPDATE TIME OF PACKET SKIPN CONN,CHRFHC ;IS THERE A RFC HANDLER HARD AT WORK? JRST CHIF35 ;NO PUSH P,PKT ;SAVE THIS OVER POTENTIAL CPYPKT HRRZ T1,CHANBF(CONN) ;YES, PUT A COPY ON THE UNHANDLED RFC QUEUE HLRZ T2,CHAWIN(CONN) ; IF THERE'S STILL ROOM IN ITS "WINDOW" CAIGE T1,(T2) CALL CPYPKT ;THERE'S ROOM IN THE WINDOW; TRY TO COPY IT JRST CHIF3U ;NO ROOM OR CAN'T, COMPLAIN MOVEI Q2,CHAIBF(CONN) ;PUT THIS COPY ON THE INPUT LIST CALL CHAQPL ; FOR OUR RFC HANDLER (DON'T NEED TO COUNT IT) AOS CHANBF(CONN) ;ACCOUNT FOR THIS NEW PACKET CHIF36: POP P,PKT ;GET BACK ORIGINAL RFC PACKET CHIF35: JUMPE F1,[MOVE F1,PKT ;REMEMBER WE HAVE SEARCHED THIS FAR JRST .+1] MOVEI Q2,CHQRFC ;PUT PACKET BACK ON RFC LIST FOR ; LISTENING SERVER TO FIND EVENTUALLY CALL CHAQPL JRST CHIF30 CHIF3U: CHABUG(CHANRU) ;COMPLAIN JRST CHIF36 ;NO ROOM IN WINDOW OR FOR PACKET; GIVE UP ;STATUS RFC CHIRFS: PUSH P,PKT MOVX T3,CHSTBC ;THIS IS BYTE COUNT FOR STATUS ANSWER GETPKT T ;GET A PACKET C(T3) BYTES LONG JRST CHIF39 ;CAN'T DO THE COPY; DON'T BOTHER WITH IT MOVE T1,[BYTE (8) .COANS,0,0,CHSTBC] MOVEM T1,(PKT) MOVE T1,CHPKS(PKT) ;EXCHANGE SOURCE AND DESTINATION EXCH T1,CHPKD(PKT) MOVEM T1,CHPKS(PKT) MOVEI T1,CHPKDT(PKT) HRLI T1,() MOVE T2,[POINT 7,MYHNAM] MOVEI T3,^D32 CHIRS1: ILDB Q2,T2 JUMPE Q2,CHIRS2 IDPB Q2,T1 SOJA T3,CHIRS1 CHIRS2: MOVEI Q2,200 ;PAD WITH 200'S IDPB Q2,T1 SOJG T3,.-1 MOVE T2,MYCHAD ;DTE SUBNET NUMBER: HIGH 8 BITS OF MY ADDRESS LSH T2,-8 IORI T2,400 ;MARK AS NEW FORMAT STATUS ANS CALL SWB16B IFE SMFLG,< ;IF DON'T HAVE DIRECT HARDWARE CONNECTION, MOVEI T2,4 ;4 MORE WORDS: CALL SWB16B MOVE T2,CHNPKI ; PACKETS IN CALL SWB32B MOVE T2,CHANPO ; AND OUT CALL SWB32B >;IFE SMFLG, IFN SMFLG,< ;ELSE, ON KS DRIVE THE INTERFACE OURSELVES: MOVEI T2,^D16 ;16 MORE WORDS CALL SWB32B SETZ T4, CHIRS3: MOVE T2,NPKSIN(T4) CALL SWB32B ;OUTPUT WORD OF STATUS CAIE T4,7 ;OUTPUT EXACTLY 16 WORDS AOJA T4,CHIRS3 >;IFN SMFLG, SETO T1, CALL CHAXMT ;AND GO ACTUALLY SEND IT, BUT DON'T BLOCK CHIF39: JRST CHIF3B ;GO RESTORE AND FREE UP THE ORIGINAL PACKET SWB32B: CALL SWB16B ;LOW 16-BITS FIRST LSH T2,-8 SWB16B: IDPB T2,T1 ;OUTPUT A 16-BIT NUMBER, SWAB'ED LSH T2,-8 IDPB T2,T1 RET ;THIS RFC MATCHES A LSN, PUT THEM TOGETHER CHIF33: HRRZ CONN,(T1) ;GET CONNECTION INDEX NOINT CALL RFCFRE ;REMOVE ENTRY FROM RFCTAB OKINT CHKCON ;VALIDATE CONN IF DEBUGGING CHKPKT ;VALIDATE PKT, TOO, IF NEEDS BE LOAD T1,CPKPN,(PKT) ;GET PACKET NUMBER HRLM T1,CHAPKN(CONN) MOVE T1,CHPKS(PKT) ;AND FOREIGN HOST STUFF MOVEM T1,CHAFRN(CONN) MOVE T1,TODCLK ;SAVE THIS AS LAST TIME OF INPUT MOVEM T1,CHAITM(CONN) SETOM PKTLNK(PKT) ;MARK AS NOT TRANSMIT ACTIVE, ON NO LISTS MOVEI Q2,CHAIBF(CONN) ;PUT ON LIST SO USER CAN SEE CONTACT NAME CALL CHAQPL MOVEI Q2,.CSRFC CALL CHAINT ;INTERRUPT PROCESS MAYBE JRST CHIF30 ;GO LOOK FOR MORE WORK ;RELEASE RCTAB ENTRY POINTED TO BY T1 RFCFRE: MOVEI T2,(T1) ;GET ADDRESS OF ENTRY PUSH P,(T2) ;SAVE ENTRY MOVEI T1,RFCTAB TBDEL ;REMOVE FROM LIST OF GUYS NEEDED ERJMP RFFREB RFFRE1: POP P,T2 HLRZ T1,T2 ;GET ADDRESS OF CONNECTION NAME SUBI T1,1 ;POINT TO HEADER HRRZ T2,(T1) ;GET LENGTH JRST RELSWP ;FREE IT UP RFFREB: CHABUG(CHARFB) ;JUST IN CASE JRST RFFREB ;SCAN NET TTY LINES EVERY BACKGROUND CYCLE OR WHEN CH%TTY GETS SET. CHATTS: IFN T20FLG,< MOVE STS,CVTPTR ;COUNT THRU NVT LINES CHATS1: HRR T2,STS ;GET TERMINAL NUMBER IN T2 PUSH P,STS ;+++SEE IF STS IS GETTING CLOBBERED CALL LCKTTY ;GET ADDRESS OF DYNAMIC DATA JUMPLE T2,CHATS2 ;IF NON-STANDARD BLOCK CHECK FOR OUTPUT PUSH P,T2 ;SAVE ADDRESS OF DYNAMIC DATA CALL TTSOBE ;ANY OUTPUT? CALL CHATCS ;YES, PROCESS IT POP P,T2 ;GET BACK ADDRESS OF DYNAMIC DATA CHATS2: CALL ULKTTY ;UNLOCK TTY DATABASE POP P,STS ;+++ AOBJN STS,CHATS1 SKIPN T2,CTMSTM ;ANY TTMSG'S OUT RET ;NOTHING TO DO RETURN CAMLE T2,TODCLK ;TIME TO FLUSH YET? RET ;NO, RETURN NOSKED ;PREVENT ANYONE ELSE FROM CHANGING DATA CALL TMSCHR ;FLUSH ALL TTMSG'S TO NVT'S OKSKED SETZM CTMSTM ;CLEAR TIMER RET >;IFN T20FLG IFN TNXFLG,< PUSH P,10 MOVE 10,NVTPTR ; COUNT THRU NVT LINES CHATS1: MOVEI 2,(10) MOVSI 1,NVTCHS TDNN 1,TTNETW(2) JRST CHATS2 ; ONLY WHEN CHAOSNET TTY SKIPN TTOCT(2) ; Output ready? SKIPE TTECT(2) CALL CHATCS ; Yes CHATS2: AOBJN 10,CHATS1 POP P,10 RET >;IFN TNXFLG SUBTTL CONSISTENCY CHECKING EVERY CYCLE CHFCC: SKIPGE CHAONC ;DID THE NET JUST GO DOWN? CHABUG(CHADWN) ;YES, NOTE THAT FACT FOR FUN SKIPLE CHAONC ;OR JUST COME UP? CHABUG(CHAUPN) ;YES RET ;THAT'S ALL FOR NOW SUBTTL HOST TABLE SUPPORT ;GET IN HOSTS2.BIN IMAGE FOR OUR HOST TABLE. ALSO SETS UP MYHNAM TO ;BE MY OFFICIAL NAME (WAITS FOR OUR HARDWARE ADDRESS TO APPEAR FROM ;THE -11 BEFORE DOING SO). ;The format of the compiled HOSTS2 file is: HSTSID==0 ; wd 0 SIXBIT /HOSTS2/ NAMPTR==10 ; wd 10 Address in file of NAME table. SITPTR==11 ; wd 11 Address in file of SITE table. NETPTR==12 ; wd 12 Address in file of NETWORK table. ;NETWORK table ; wd 0 Number of entries in table. ; wd 1 Number of words per entry. (2) NETNUM==0 ; wd 0 network number NTLNAM==1 ; wd 1 LH - address in file of name of network NTRTAB==1 ; wd 1 RH - address in file of network's address table ;ADDRESS table(s) ; wd 0 Number of entries in table. ; wd 1 Number of words per entry. (2) ADDADR==0 ; wd 0 Network address of this entry including network number ADD%NW==377000000000 ;Network number portion of address ADD%CA==000000177777 ;Chaosnet hardware address portion ADLSIT==1 ; wd 1 LH - address in file of SITE table entry ADRCDR==1 ; wd 1 RH - address in file of next ADDRESS entry for this site ; 0 = end of list ;SITE table ; wd 0 Number of entries in table. ; wd 1 Number of words per entry. (3) STLNAM==0 ; wd 0 LH - address in file of official host name STRADR==0 ; wd 0 RH - address in file of first ADDRESS table entry for ; this site. Successive entries are threaded ; together through ADRCDR. ;NAMES table: ; wd 0 Number of entries ; wd 1 Number of words per entry. (1) NMLSIT==0 ; lh address in file of SITE table entry for this host. NMRNAM==0 ; rh address in file of host name ; All names are ASCIZ strings, all letters upper case. ; The strings are stored before, after and between the tables. ; All strings are word-aligned, and fully zero-filled in the last word. ;Network addresses are defined as follows, for purposes of this table: ; 4.9 0 ; 4.8-4.1 network number ; Chaos net (number 7): ; 3.9-2.8 0 ; 2.7-1.1 address (2.7-1.9 subnet, 1.8-1.1 host) ; ARPANET (number 12): (note, old-format ARPANET addresses ; 3.9-3.8 0 never appear in the host table.) ; 3.7-2.1 IMP ; 1.9 0 ; 1.8-1.1 Host ; Dialnet (number 26): ; 3.9-3.1 0 ; 2.9-1.1 address in file of ASCIZ string of phone number NOMNAM: MYNAME ;NOMINAL HOST NAME AT BUILD TIME IFE CHADTE,< RESCD CHWHST: MOVE T1,MYHTIM ;GET LIMIT OF WAIT CAMLE T1,TODCLK ;IS TIME UP YET? SKIPL MYCHAD ; OR HAS MY ADDRESS APPEARED YET? JRST 1(T4) ;YES, UNBLOCK JRST 0(T4) ;NO SWAPCD >;IFE CHADTE, CHSINI: STKVAR ;ERROR FLAG, HOSTS2.BIN JFN, MY FULL CHAOS ADDRESS SETZM CINERR ;NO ERROR YET SETOM CINHFJ ;NO JFN YET SETZM MYHNAM ;MAKE SURE WE KNOW WE DON'T KNOW OUR NAME YET IFN DTEFLG, ;WAIT UP TO 10 SECONDS FOR MOVEM T1,MYHTIM ; MY HARDWARE ADDRESS TO APPEAR FROM -11 MOVEI T1,CHWHST ;WAIT FOR MY ADDRESS SKIPL MYCHAD ;UNLESS IT'S ALREADY HERE JRST CHSIN1 ;YEP HDISMS(^D500) ;WAIT CHSIN1: SKIPGE MYCHAD ;DID IT ACTUALLY ARRIVE? CHABUG(CHAINH) ;NO, COMPLAIN ABOUT IT >>;IFE CHADTE, IFN DTEFLG, MOVX T1,GJ%OLD!GJ%SHT ;NOW, TRY TO FIND HOSTS2.BIN IFN T20FLG,< HRROI T2,[ASCIZ/SYSTEM:HOSTS2.BIN/] > IFN TNXFLG,< HRROI T2,[ASCIZ/HOSTS2.BIN/] > GTJFN ERJMP [MOVEI T1,0 ;CAN'T, COMPLAIN AND GET OUT JRST CHSIER] ; WITH ERROR TYPE MOVEM T1,CINHFJ ;GOT IT, REMEMBER THIS JFN MOVE T2,[2,,.FBBYV] ;GET THE BYTE SIZE INFO AND NUMBER OF BYTES MOVEI T3,T3 ; TO T3, T4 GTFDB ERJMP [MOVEI T1,1 ;CAN'T, GIVE UP JRST CHSIER] EXCH T3,T4 ;T3/ NUMBER OF BYTES, T4/.FBBYV INFO LDB T2,[POINTR(T4,FB%BSZ)] ;GET ACTUAL BYTE SIZE LSH T2,<^D35-POS(OF%BSZ)> ;SHIFT IT INTO PLACE FOR OPENF IORX T2,OF%RD ;WE SIMPLY WANT TO READ THE FILE OPENF ;GET IT OPEN ERJMP [MOVEI T1,2 ;FAILED; GIVE UP JRST CHSIER] LDB T2,[POINTR(T4,FB%PGC)] ;GET PAGE COUNT CAILE T2,CHST2P ;WILL IT FIT? JRST [ MOVEI T1,3 ;NOPE, GIVE UP JRST CHSIER] LDB T2,[POINTR(T4,FB%BSZ)] ;GET BACK BYTE SIZE LSH T2,^D35-POS(<007700,,0>) ;SHIFT IT INTO PLACE FOR BP SIZE FIELD TLO T2,440000 ;BUILD BYTE REF TO OUR HOST TABLE START HRRI T2,CHOSTB MOVNS T3 ;NOW, GET SET TO SIN IT ALL IN SIN ;TRY IT ERJMP [MOVEI T1,4 ;SOMETHING FAILED, JRST CHSIER] ; NOTE IT MOVE T1,CHOSTB+HSTSID ;PICK UP PURPORTED SELF-ID CAME T1,[SIXBIT/HOSTS2/] ;IS IT OK? JRST [ MOVEI T1,5 ;NO, FAIL JRST CHSIER] MOVE T1,CHOSTB+NETPTR ;YES, GET REF TO START OF NETWORK TABLE DMOVE T2,CHOSTB(T1) ;NUMBER OF ENTRIES AND SIZE OF EACH MOVEI T1,CHOSTB+2(T1) ;FIRST ENTRY ADDRESS (REAL) CHSIN2: HLRZ T4,NTLNAM(T1) ;GET REF TO NAME OF THIS NET MOVE T4,CHOSTB(T4) ;GET NAME CAME T4,[ASCII/CHAOS/] ;THIS US? SOJG T2,[ADDI T1,(T3) ;NO, BUMP TO NEXT ENTRY IF ANY MORE JRST CHSIN2] ; AND TRY IT JUMPLE T2,[MOVEI T1,6 ;COULDN'T FIND OUR NET NUMBER, COMPLAIN JRST CHSIER] MOVE T2,NETNUM(T1) ;GOT IT, PICK UP OUR NUMBER MOVEM T2,CHANET ;SAVE IT HERE SETOM CHOSTP ;NOW HAVE A TOTALLY KOSHER HOST TABLE READY SKIPGE MYCHAD ;HAVE OUR ADDRESS? JRST CHSIN4 ;NO, TRY TO WORK THE OTHER WAY (FROM OUR NAME) LSH T2,<^D35-POS(ADD%NW)> ;PUT IT IN THE NETWORK FIELD IOR T2,MYCHAD ;BUILD MY FULL HOSTS2 ADDRESS HERE MOVEM T2,CINFAD ;SAVE IT FOR SCAN BELOW HRRZ T1,NTRTAB(T1) ;GET OFFSET OF ADDRESS TABLE FOR CHAOSNET MOVEM T1,CHANAO ;REMEMBER IT FOR LATER LOOKUPS DMOVE T2,CHOSTB(T1) ;GET NUMBER OF ENTRIES AND SIZE OF EACH MOVEI T1,CHOSTB+2(T1) ;GET REAL REF TO FIRST ENTRY CHSIN3: MOVE T4,ADDADR(T1) ;GET THIS ENTRY'S ADDRESS CAME T4,CINFAD ;IS IT I? SOJG T2,[ADDI T1,(T3) ;NO, BUMP TO NEXT IF ANY MORE JRST CHSIN3] ; AND KEEP LOOKING JUMPLE T2,[MOVEI T1,7 ;COULDN'T FIND MY NAME JRST CHSIER] HLRZ T1,ADLSIT(T1) ;GET OFFSET OF SITE ENTRY FOR ME HLRZ T1,CHOSTB+STLNAM(T1) ;GET OFFICIAL HOST NAME OFFSET ADD T1,[POINT 7,CHOSTB] ;TURN INTO BP SKIPA ;HAVE OUR NAME REF IN T1 CHSIN4: MOVE T1,[POINT 7,NOMNAM] ;DON'T KNOW OUR ADDRESS, USE NOMINAL NAME MOVE T2,[POINT 7,MYHNAM] ILDB T3,T1 ;MOVE IN MY ASCIZ OFFICIAL HOSTS2 NAME IDPB T3,T2 JUMPN T3,.-2 SKIPL MYCHAD ;STILL IN THE DARK ABOUT MY ADDRESS? JRST CHSIDN ;NO, GET OUT MOVEI T1,MYHNAM-1 ;YES, FIND OUR ADDRESS THE OTHER WAY CALL HSTNAM SKIPA ;IF FAILS, SKIPN T1 ; OR IF OUR NAME ISN'T FOUND JRST [ MOVEI T1,10 ;REMEMBER THIS PROBLEM JRST CHSIER ] MOVEM T1,MYCHAD ;ELSE, REMEMBER MY HOST ADDRESS JRST CHSIDN ;ALL SET, GO CLEAN UP ;HERE ON ERROR CHSIER: MOVEM T1,CINERR ;NOTE SOME PROBLEM ;HERE WHEN DONE,TO CLEAN UP CHSIDN: SKIPL T1,CINHFJ ;GET JFN IF ANY CLOSF ; AND TRY TO CLOSE IT ERJMP .+2 ;IF FAILS, TRY TO JUST RELEASE IT JRST CHSIED ;NO JFN OR CLOSF WORKED, SKIP THE RELEASE RLJFN ;GET RID OF THE JFN ERJMP .+1 ;AGAIN, IGNORE FILE ERRORS CHSIED: SKIPE T1,CINERR ;ANY REAL PROBLEMS ABOVE? CHABUG(CHANHT,<>) ;YES, COMPLAIN APPROPRIATELY RET ;CONVERT HOSTNAME STRING (JFN NAME BLOCK REF IN T1) TO NUMBER HSTNAM: JUMPE T1,RSKP ;RETURN 0 (BUT OK) IF NO STRING SAVEAC ;SAVE WORK REGS STKVAR ,LHSTNS> ;ORIGINAL STRING, COPY OF STRING, WD LENGTH HRLI T1,() MOVEM T1,OHSTNT ;SAVE NAME REF FOR LATER USE ILDB T1,T1 ;GET FIRST JUMPE T1,RSKP ;IF NULL STRING, RETURN NULL (BUT OK) SKIPN CHOSTP ;HAVE A HOST TABLE? JRST HSTNM1 ;NONE, TRY NUMBER SPEC MOVEI T1,HSTNS ;CLEAR OUR SETZM (T1) MOVSI T2,(T1) ; LOCAL HOST FELLOW FOR WORD COMPARISON PURPOSES HRRI T2,1(T1) MOVEI T1,^D50/5-1(T1) BLT T2,(T1) MOVE T1,OHSTNT ;GET BACK ORIGINAL HOST SPEC MOVNI T3,^D100 ;LIMIT COUNTER MOVEI T2,HSTNS ;WHERE WE BUILD OUR WORD-COMPARABLE HOSTNAME HRLI T2,440700 HSTNM0: ILDB T4,T1 CAIL T4,"a" CAILE T4,"z" CAIA TRZ T4,40 ;UPPER-CASIFY ALPHABETICS FOR SAFETY IDPB T4,T2 SKIPE T4 AOJL T3,HSTNM0 JUMPGE T3,HSTNM1 ;TOO LONG, TRY NUMBER JUST FOR SPITE SETZ T4, TLNN T2,760000 ;FILL OUT TO FULL WORD JRST .+3 IDPB T4,T2 JRST .-3 HRRZS T2 ;GET ADDRESS OF LAST WORD STORED SUBI T2,HSTNS ;GET LENGTH IN WORDS-1 MOVEI T2,1(T2) ;ADJUST MOVNM T2,LHSTNS ;SAVE NEGATIVE FOR AOBJN USE BELOW MOVE T1,CHOSTB+NAMPTR ;GET OFFSET OF NAMES TABLE DMOVE T2,CHOSTB(T1) ;NUMBER OF ENTRIES AND SIZE OF EACH MOVEI T1,CHOSTB+2(T1) ;REAL REF TO FIRST ENTRY HSTNM7: HRRZ T4,NMRNAM(T1) ;PICK UP NAME OFFSET MOVEI T4,CHOSTB(T4) ;TURN INTO REAL ADDRESS MOVEI F1,HSTNS ;THIS IS COMPARAND HRL F1,LHSTNS ;MAKE LOOP CONTROLLER HSTNM8: MOVE Q2,(F1) ;SEE IF WORD-EQUAL CAME Q2,(T4) JRST [ ADDI T1,(T3) ;NO, BUMP TO NEXT ENTRY SOJG T2,HSTNM7 ; AND GO ON IF ANY MORE JRST HSTNM1 ] ;NO MORE, TRY NUMBER MOVEI T4,1(T4) AOBJN F1,HSTNM8 ;COMPARE ALL WORDS HLRZ T1,NMLSIT(T1) ;FOUND IT; PICK UP SITE OFFSET FOR THIS GUY HRRZ T1,CHOSTB+STRADR(T1) ;PICK UP FIRST ADDRESS ENTRY OFFSET FOR THIS SITE HSTNM9: JUMPE T1,HSTNM1 ;RAN OUT OF ENTRIES, TRY NUMBER SPEC MOVE T2,CHOSTB+ADDADR(T1) ;GET THIS ADDRESS LDB T3,HNMPNW ;PICK OUT NETWORK NUMBER CAME T3,CHANET ;IS THIS A CHAOS HOST ADDRESS? JRST [ HRRZ T1,CHOSTB+ADRCDR(T1) ;NO, CDR DOWN LIST OF ADDRESSES JRST HSTNM9 ] ;AND KEEP LOOKING LDB T1,HNMPCA ;GET REAL HARDWARE ADDRESS RETSKP ;DONE HNMPNW: POINTR T2,ADD%NW HNMPCA: POINTR T2,ADD%CA ;TRY FOR A NUMBER SPEC IF THE ABOVE HAIR FAILS HSTNM1: SETZ T1, ;BUILD HOST NUMBER HERE MOVE T2,OHSTNT ;GET BACK ORIGINAL SPEC REF HSTNM2: ILDB T3,T2 JUMPE T3,RSKP CAIL T3,"0" CAILE T3,"7" RET LSH T1,3 ADDI T1,-"0"(T3) JRST HSTNM2 RESCD ;HARDWARE SUPPORT ROUTINES IFN DTEFLG,< SUBTTL DTE SERVICE IFN CHADTE,< ;FROM -11 STATUS CHSSTS: MOVE T1,[-CHASBS,,CHASBL] ;POINT TO STATUS BLOCK CHSST1: ILDB T3,T2 MOVEM T3,(T1) AOBJN T1,CHSST1 SETOM CHAON ;SAY NET IS ON CALL GATINC ;POKE INTERNET GATEWAY RET ;ACK FROM -11 CHADON: SOS T1,CHNPO1 ;ONE LESS PACKET OUTSTANDING IN -11 MOVEI T2,1 ;FOR CHNPOW RESET CAMGE T1,CHNPOW ;DID WE GET BELOW SOMEONE'S WATCHDOG LIMIT? MOVEM T2,CHNPOW ;YES, NOTE THAT FACT RET ;-11 CRASHED, TURN OFF NET; THIS WILL EVENTUALLY CAUSE ALL CONNECTIONS TO GO .CSINC DEDMCB::SETZM CHAON RET ;-11 RELOAD ACTION, ALSO CALLED ONCE AT STARTUP NODINI:: CHARLD: SETZM CHAON ;NETWORK OFF FOR NOW MOVNI T1,^D10 ;NUMBER OF PACKETS TO ALLOW OUTSTANDING IN -11 MOVEM T1,CHNPO1 MOVEI T1,CHADTE MOVE T2,[POINT 16,[BYTE (16) 0,1]] MOVEI T3,2 CALL DTEQ JFCL ;WILL GET SENT EVENTUALLY RET ;PACKET FROM -11 CHAPKT: MOVEI PKT,1(T2) ;FALL INTO CHIPKT WITH PACKET SET UP IF2,> ;DOUBLE-CHECK >;IFN CHADTE IFE CHADTE,< ;FROM -11 STATUS CHSSTS: MOVE T1,[-CHASBS,,CHASBL] ;POINT TO STATUS BLOCK CHSST1: ILDB T2,T4 LSH T2,8 ILDB T3,T4 IORI T2,(T3) MOVEM T2,(T1) AOBJN T1,CHSST1 SETOM CHAON ;SAY NET IS ON MOVEI T1, CALL GATINC ;POKE INTERNET GATEWAY RET ;ACK FROM -11 CHADON: JUMPL T2,R ;IGNORE ACK ALL SOS T1,CHNPO1 ;ONE LESS PACKET OUTSTANDING IN -11 MOVEI T2,1 ;FOR CHNPOW RESET CAMGE T1,CHNPOW ;DID WE GET BELOW SOMEONE'S WATCHDOG LIMIT? MOVEM T2,CHNPOW ;YES, NOTE THAT FACT RET ;-11 RELOAD ACTION, ALSO CALLED ONCE AT STARTUP CHARLD: SETZM CHAON ;NETWORK OFF FOR NOW MOVNI T1,^D10 ;NUMBER OF PACKETS TO ALLOW OUTSTANDING IN -11 MOVEM T1,CHNPO1 MOVSI T1,0 ;GET HOSTNUMBER AND RELATED INFO FROM -11 MOVE T2,[.DFRDS,,.FECHA] ;REQUEST DEVICE STATUS SETZB T3,T4 CALL DTEQ JFCL RET ;STRING DATA FROM -11 CHAHSD: MOVE T3,(T4) ;FIRST WORD IS BYTE OFFSET INTO PACKET LSH T3,-24 ;INTO T3 MOVE T2,(T4) ;NEXT IS NUMBER OF BYTES STILL TO COME LSH T2,-4 ANDI T2,177777 ;INTO T2 SUBI T1,4 ;ACCOUNT FOR OUR HEADER JUMPN T2,CHAHS1 ;IF BYTES STILL TO COME THIS PACKET JUMPE T3,CHAHS2 ;OR IT IS OFFSET ANY CHAHS1: ADDI T1,3(T3) ;LAST DESTINATION BYTE, AND READY TO ROUND UP LSH T3,-2 ;MAKE WORD OFFSET (NOTE OFFSET REM 4 = 0) LSH T1,-2 ;AND THIS ALSO MOVEI T3,CHBGPK(T3) ;POINT INTO THE BIG PACKET HRLI T3,1(T4) ;SOURCE IS DTE BUFFER WITH PACKET IN IT BLT T3,CHBGPK(T1) ;COPY INTO BIG PACKET JUMPN T2,R ;DONE IF MORE DATA TO COME SKIPA PKT,[CHBGPK] ;HAVE ROUTINES PROCESS THE BIG PACKET CHAHS2: MOVEI PKT,1(T4) ;THIS IS A SHORT PACKET, USE DTE BUFFER ITSELF JRST CHIPKT >;IFE CHADTE >;IFN DTEFLG IFN SMFLG,< SUBTTL KS10-CHAOS INTERFACE SUPPORT ;;; HERE TO REINITIALIZE THE HARDWARE CHARLD: SETZM CHAON ;ASSUME CHAOSNET IS OFF MOVE T1,[CHAADR] ;CHECK FOR EXISTANCE OF CHAOS INTERFACE CALL UBGOOD RET ;IT'S NOT THERE, SO CHAOSNET IS OFF SETZM CHAXPC+2 ;SETUP XPCW BLOCK MOVEI T1,CHAHIN MOVEM T1,CHAXPC+3 MOVE T1,[XPCW CHAXPC] ;THIS IS THE INTERRUPT INSTRUCTION MOVE T2,SMTEPT+CHAUBN ;INTERRUPT VECTOR FOR OUR UNIBUS ADAPTOR ADDI T2,CHAVEC/4 ;OFFSET BASED ON OUR INTERRUPT VECTOR MOVEM T1,(T2) ;PLANT INTERRUPT INSTRUCTION MOVE T1,[CHAADR] MOVEI T2,CHSRST ;RESET THE INTERFACE WRIO T2,CHACSR(T1) RDIO T2,CHAMYN(T1) ;READ OUR HOST NUMBER MOVEM T2,MYCHAD ;AND REMEMBER IT SETZM CHATXQ ;CLEAR TRANSMIT QUEUE SETOM CHAON ;SAY NETWORK IS ON MOVEI T2,CHSTCL+CHSRCL+CHSREN WRIO T2,CHACSR(T1) ;CLEAR TRANSMITTER AND RECEIVER, AND ENABLE ; RECEIVER INTERRUPTS RET CHAHIN: MOVEM 17,CHAACS+17 ;SAVE AC 17 MOVEI 17,CHAACS ;THEN SAVE REMAINDER WITH A BLT BLT 17,CHAACS+16 MOVE 17,[-CHAIPS,,CHAIPL] ;INTERRUPT LEVEL PDL MOVE T1,[CHAADR] ;CHAOSNET I/O ADDRESS RDIO T2,CHACSR(T1) ;GET CURRENT DEVICE STATUS TRNE T2,CHSRDN ;RECEIVE DONE -- GO HANDLE INTERRUPT JRST CHAIRV TRNE T2,CHSTEN ;TRANSMITTER INTERRUPT EXPECTED? JRST CHAITX ;YES, CHECK TO SEE IF THAT'S IT CHASPU: CHABUG(CHASPI,<>) ;SPURIOUS INTERRUPT, SHOULDN'T HAPPEN CALL CHARLD ;THIS KNOWS HOW TO REALLY RESET THE WORLD ;;; RETURN FROM INTERRUPT CHAIRT: MOVSI 17,CHAACS ;RESTORE ALL AC'S BUT 17 BLT 17,16 MOVE 17,CHAACS+17 ;NOW RESTORE 17 XJEN CHAXPC ;THEN RETURN FROM WHENCE WE CAME... ;;; HERE WHEN WE SUSPECT THE TRANSMITTER CHAITX: TRNN T2,CHSTDN ;TRANSMIT DONE? JRST CHASPU ;NOPE, SPURIOUS INTERRUPT PIOFF ;WILL BE HACKING THE QUEUE HRRZ PKT,CHATXQ ;THIS IS THE PACKET WE JUST TRANSMITTED TRNE T2,CHSTAB ;TRANSMIT ABORTED? JRST CHATXA ;YES, HANDLE DIFFERENTLY CHATXB: HRRZ T1,PKTTLK(PKT) ;NEXT PACKET TO GO SETZM PKTTLK(PKT) ;MAKE SURE NOBODY LOOKS AT THIS INFO HLRZ T2,CHATXQ ;GET LAST PACKET ON QUEUE FOR ERROR CHECK JUMPN T1,CHATX0 ;SOMETHING THERE, TRANSMIT IT SETZM CHATXQ ;CLEAR THE QUEUE PION ;DONE HACKING WITH IT ALSO CAME T2,PKT ;IS QUEUE CONSISTENT? CHATX1: CHABUG(CHATQF) ;TRANSMIT QUEUE IS INCONSISTENT CALL CHAXIN ;PACKET IS DONE BEING TRANSMITTED MOVE T1,[CHAADR] MOVEI T2,CHSTEN BCIO T2,CHACSR(T1) ;TURN OFF TRANSMITTER INTERRUPT ENABLE JRST CHAIRT ;DISMISS INTERRUPT CHATX0: CAMN T2,PKT ;THE PACKET WE JUST SENT BETTER NOT HAVE BEEN ; THE LAST ONE! JRST [SETZM CHATXQ ;ERROR, REPORT IT AND FLUSH QUEUE PION JRST CHATX1] HRRM T1,CHATXQ ;THIS PACKET IS THE NEXT TO GO PUSH P,T1 ;SAVE FOR LATER PION ;DONE WITH QUEUE FOR NOW CALL CHAXIN ;REPORT PACKET AS TRANSMITTED POP P,PKT ;GET THAT PACKET BACK CALL CHATXP ;SEND IT OFF JRST CHAIRT ;THEN DISMISS INTERRUPT ;;; HERE IF TRANSMIT ABORTED (PI SYSTEM IS OFF) CHATXA: AOS NPKSAB ;COUNT THE ABORT HLRZ T1,PKTTLK(PKT) ;GET THE RETRANSMISSION COUNT AOS T1 ;ONE MORE TIME CAILE T1,CHARTC ;OK TO RETRANSMIT JRST CHATXB ;NOPE, SO TREAT AS IF SUCCESFUL HRRZ T2,PKTTLK(PKT) ;GET NEXT PACKET HRLZM T1,PKTTLK(PKT) ;REMEMBER THE NUMBER OF TIMES ;;; *** THIS IS A CROCK -- IT SHOULD WAIT 1/60 OF A SEC OR SO, BUT THAT'S ;;; *** TOO HARD FOR NOW SO IT'LL WORK THIS WAY JUMPE T2,CHATXC ;WE ARE THE ONLY ONE, SO SEND US OFF RIGHT NOW HRRM T2,CHATXQ ;PROMOTE NEW PACKET TO THE HEAD OF THE QUEUE HLRZ T1,CHATXQ ;LAST PACKET ON QUEUE HRRM PKT,PKTTLK(T1) ;LINK US IN HRLM PKT,CHATXQ ;AND MAKE US LAST MOVEI PKT,(T2) CHATXC: PION ;QUEUES ARE CONSISTENT, TRANSMIT THE NEXT PKT CALL CHATXP ;SEND IT OFF JRST CHAIRT ;THEN DISMISS THE INTERRUPT ;;; HERE TO TRANSMIT PACKET IN PKT. THE INTERFACE BETTER BE READY FOR ONE! CHATXP: MOVE T1,[CHAADR] MOVEI T2,CHSTCL BSIO T2,CHACSR(T1) ;CLEAR TRANSMITTER MOVE T4,[<442000,,0>(PKT)] ;BYTE POINTER TO BEGINNING OF PACKET REPEAT 10,< ;OUTPUT THE 16 HEADER BYTES ILDB T2,T4 WRIO T2,CHAWBF(T1) > LOAD T3,CPKNB,(PKT) ;NUMBER OF DATA BYTES AOS T3 LSH T3,-1 ;ROUND OFF TO NUMBER OF 16 BIT WORDS JUMPE T3,CHATP1 ;ONLY HEADER, SKIP DATA TRANSMISSION STUFF LOAD T2,CPKOP,(PKT) ;GET THE OPCODE CAIE T2,.COOPN ;16 BIT CONTROL OPCODE? CAIN T2,.COSTS JRST CHATP2 CAIN T2,.CORUT JRST CHATP2 CAIGE T2,.CODAT+100 ;BINARY DATA? JRST CHATP0 ;NOPE, USE THE SLOW LOOP CHATP2: ILDB T2,T4 WRIO T2,CHAWBF(T1) ;WRITE DATA WORD TO INTERFACE SOJG T3,CHATP2 CHATP1: ;;; *** HERE IT SHOULD ROUTE, BUT FOR NOW JUST SEND IT OUT TO THE SPECIFIED ;;; *** HOST ON SUBNET 1 (OUR OWN SUBNET) LOAD T2,CPKDA,(PKT) WRIO T2,CHAWBF(T1) RDIO T2,CHAXMT(T1) ;TRANSMIT THE THING MOVEI T2,CHSTEN ;AND ENABLE TRANSMITTER INTERRUPTS BSIO T2,CHACSR(T1) RET ;;; HERE WHEN NEED TO DO BYTE SWAPPING ON OUTPUT CHATP0: MOVE T4,[<441000,,CHPKDT>(PKT)] ;8 BIT BYTE POINTER CHATP4: ILDB T2,T4 ;GET NEXT BYTE ILDB Q2,T4 ;THIS NEEDS TO BE HIGH ORDER BYTE DPB Q2,[101000,,T2] ;SO PLANT IT IN AC WRIO T2,CHAWBF(T1) ;WORD OUT TO INTERFACE SOJG T3,CHATP4 JRST CHATP1 ;;; HERE TO RECEIVE A PACKET, T2 HAS HARDWARE CSR, T1 HAS CHAOS BASE ADDRESS CHAIRV: AOS NPKSIN ;COUNT THIS AS ANOTHER PACKET IN FORM INTERFACE TRNE T2,CHSERR ;CRC ERROR? JRST CHARV5 ;YES, COUNT IT, FLUSH THE PACKET, THEN PROCEED RDIO Q2,CHARBF(T1) ;GET FIRST 16 BIT WORD, WHICH CONTAINS OPCODE LSH Q2,-8 ;SHIFT OPCODE INTO POSITION RDIO T2,CHARBF(T1) ;NEXT WORD IS FORWARDING COUNT AND LENGTH MOVEI T1,3(T2) ;GET NUMBER OF BYTES IN PACKET + 3 TO ROUND LSH T1,-2 ;CONVERT TO NUMBER OF PDP-10 WORDS PUSH P,T2 ;SAVE T2 OVER CALL TO ASGPKI CAIG T1,CHPMXW ;DON'T READ HARDWARE IF PACKET TOO LARGE CALL ASGPKI ;GET APPROPRIATLY SIZED PACKET JRST [POP P,T2 AOS NPKSIG ;COUNT THIS PACKET IGNORED FOR "OTHER REASONS" CALL CHARVR ;RESET RECEIVER JRST CHAIRT] ;PUNT RECEIVE -- RESET HARDWARE AND DISMISS INT POP P,T2 ;RESTORE BYTE COUNT HRLZI T4,042000 ;POINT TO SIZE/FORWARDING COUNT FIELD HRRI T4,(PKT) DPB T2,T4 ;THEN STORE 16 BITS MOVE T1,[CHAADR] ;GET BACK CHAOS INTERFACE ADDRESS REPEAT 6,< RDIO T2,CHARBF(T1) ;READ NEXT WORD IDPB T2,T4 >;END REPEAT LOAD T3,CPKNB,(PKT) ;BYTE COUNT JUMPE T3,CHARV2 ;NO DATA, SKIP READING ANY AOS T3 LSH T3,-1 ;NUMBER OF 16 BIT WORDS ANDI Q2,377 ;OPCODE PART CAIE Q2,.COOPN ;16 BIT CONTORL OPCODE? CAIN Q2,.COSTS JRST CHARV0 CAIE Q2,.CORUT CAIL Q2,.CODAT+100 ;BYTE SWAP NECESSARY? JRST CHARV0 ;NOPE, JUST READ THEM IN FAST MOVE CONN,[201000,,T2] ;BYTE POINTER FOR REVERSING BYTES CHARV1: RDIO T2,CHARBF(T1) ;READ NEXT 16 BIT WORD DPB T2,CONN ;DUPLICATE LOW ORDER BYTE LSH T2,-10 ;THEN FLUSH EXTRA COPY OF LOW ORDER BYTE IDPB T2,T4 ;AND STORE WORD IN MEMORY SOJG T3,CHARV1 ;LOOP UNTIL NO MORE CHARV2: RDIO T2,CHARBF(T1) ;THIS IS THE HARDWARE DESTINATION RDIO T3,CHARBF(T1) ;THIS IS THE HARDWARE SOURCE RDIO T4,CHARBF(T1) ;THIS IS THE CHECKSUM RDIO T4,CHARBC(T1) ;THE BIT COUNT CAIE T4,7777 ;IS THE BIT COUNT CORRECT? JRST CHARV3 ;NO, BAD BIT COUNT -- FLUSH THE PACKET RDIO T4,CHACSR(T1) ;CHECK IF GOT CRC ERROR AFTER READING OUT TRNE T4,CHSERR JRST CHARV4 ;YES, COUNT IT AND RETURN PACKET CALL CHARVR ;RESET RECEIVER CALL CHIPKT ;HANDLE THIS PACKET JRST CHAIRT ;DISMISS INTERRUPT ;;; FAST(ER) DATA LOOP CHARV0: RDIO T2,CHARBF(T1) ;GET 16 BIT BYTE IDPB T2,T4 ;PLANT IN PACKET SOJG T3,CHARV0 ;LOOP UNTIL NO MORE JRST CHARV2 ;;; ERROR ROUTINES CHARV5: AOS NPKSER ;CRC ERROR BEFORE READING CALL CHARVR ;RESET RECEIVER JRST CHAIRT ;THEN RETURN FROM INTERRUPT CHARV3: AOSA NPKSBB ;BAD BIT COUNT CHARV4: AOS NPKSRE ;CRC ERROR AFTER READOUT CALL RELPKT ;RETURN PKT TO FREE POOL CALL CHARVR ;RESET RECEIVER JRST CHAIRT ;THEN DISMISS INTERRUPT ;;; RESET RECEIVER CHARVR: MOVE T1,[CHAADR] RDIO T2,CHACSR(T1) ;ACCOUNT FOR LOST PACKETS LDB T3,[110400,,T2] ADDM T3,NPKSLS MOVEI T3,CHSRCL ;THEN CLEAR THE RECEIVER BSIO T3,CHACSR(T1) RET ;;;NORMAL-ROUTING PACKET OUTPUT FOR KS10 (CALLED FROM CHAXMT) CHXNOR: AOS NPKSOU ;ONE MORE OUTPUT TO HARDWARE SKIPN CHAON ;IF NET ISN'T REALLY ON, DON'T SEND PACKET JRST CHAXIN ;SO MAKE BELIEVE IT MADE IT OUT PIOFF ;HACK QUEUES UNINTERRUPTABLY SKIPN T1,CHATXQ ;ARE WE CURRENTLY TRANSMITTING? JRST [MOVEI T1,(PKT) ;NOPE, SO QUEUE UP THE PACKET HRLI T1,(PKT) MOVEM T1,CHATXQ SETZM PKTTLK(PKT) ;LAST PACKET IN QUEUE PION ;TURN PI SYSTEM BACK ON JRST CHATXP] ;THEN SEND THE PACKET OUT THE INTERFACE HLRZ T1,T1 ;GET LAST PACKET ON QUEUE HRRM PKT,PKTTLK(T1) ;LINK US TO IT HRLM PKT,CHATXQ ;WE ARE NOW LAST PACKET ON QUEUE SETZM PKTTLK(PKT) ;FLAG THAT IN PACKET AS WELL PION ;DONE HACKING QUEUES RET >;END IFN SMFLG IFN CHDR11,< SUBTTL FOONLY DR11 SUPPORT ;SPECIAL LOCATIONS TO INTERFACE TO MICROCODE DRINPD=2000 ;INPUT DONE LIST DROUTD=2001 ;OUTPUT DONE LIST DRINPR=2002 ;INPUT READY LIST DROUTR=2003 ;OUTPUT READY LIST DRINPP=2004 ;INPUT PACKET IN PROGRESS DROUTP=2005 ;OUTPUT PACKET IN PROGRESS ;SPECIAL INSTRUCTIONS FOR HACKING DR11 OPDEF DR11R [744000,,0] ;RESET STATE OPDEF DR11WI [744040,,0] ;WAKE UP INPUT MICROCODE OPDEF DR11WO [744100,,0] ;WAKE UP OUTPUT MICROCODE OPDEF DR11O [745000,,0] ;EFFECTIVE ADDRESS TO PDP-11 ;INITIALIZE DR11 INTERFACE CHARLD: DR11R 60 ;TURN OFF MICRO-INTERRUPTS MOVE T1,[DRINPD,,DRINPD+1] SETZM -1(T1) BLT T1,DROUTP ;CLEAR OUT SPECIAL LOCATIONS DR11O 0 ;SEND 0 TO 11 MOVEI Q2,^D5 ;MAKE SOME INPUT PACKETS CDRIN1: MOVE T1,[.RESP1,,^D128] MOVEI T2,.RESNP CALL ASGRES CHABUG(CHDR1F) MOVSI T3,^D254 MOVEM T3,(T1) MOVEI T2,DRINPR CALL DR11Q ;PUT ON END OF INPUT QUEUE SOJG Q2,CDRIN1 DR11WI ;INPUT WAKEUP SETOM CHAON ;NOW CAN DO THINGS RET ;CALLED FROM CLOCK LEVEL TO CHECK ON THINGS CCHKDR: CKDRIN: SETZ T1, EXCH T1,DRINPD ;GET INPUT DONE LIST JUMPE T1,CKDRIR ;NO INPUT, CHECK OUTPUT HLRZ T1,T1 ;GET HEAD OF LIST CKDRI1: PUSH P,T1 ;SAVE ADDRESS MOVEI PKT,1(T1) ;POINT TO PACKET DATA CALL CHIPKT ;HANDLE IT POP P,T1 MOVSI T3,^D254 ;MAXIMUM NUMBER OF INPUT BYTES EXCH T3,(T1) ;GET CDR AND RESET SIZE AND CDR MOVEI T2,DRINPR ;PUT BACK ON INPUT READY LIST CALL DR11Q DR11WI ;LET IT GET FULL MOVEI T1,(T3) ;GET CDR JUMPN T1,CKDRI1 ;AND PROCESS IT IF NECESSARY CKDRIR: ;CHECK ON OUTPUT CKDROU: SETZ T1, EXCH T1,DROUTD JUMPE T1,CKDROR HLRZ T1,T1 ;GET HEAD OF LIST CKDRO1: PUSH P,T1 ;SAVE IT MOVEI PKT,1(T1) ;POINT TO PACKET ITSELF PKTPTH [61] ;NOTE WE GOT HERE WHEN DEBUGGING DEBUG,< HLRZ T1,PKTLNK(PKT) ;PICK UP XMIT ACTIVE FLAG MOVE T2,PKTMAG(PKT) ;GET MAGIC FIELD IF DEBUGGING CAIE T1,1 ;BETTER BE WHAT WE LEFT IT AT CHABUG(CHAXIB,<,,>) ;NO, COMPLAIN >;DEBUG HRROS PKTLNK(PKT) ;CLEAR TRANSMIT ACTIVE RCALL RELPKM,16 POP P,T1 ;GET BACK PACKET HRRZ T1,(T1) ;GET CDR JUMPN T1,CKDRO1 ;AND PROCESS IT CKDROR: RET ;ALL DONE ;TRANSMIT A PACKET CHXNOR: CHXDR1: NOSKD1 ;LOCK OUT ANY OTHERS PKTPTH [60] ;REMEMBER WE'VE BEEN HERE MOVE T1,TODCLK ;SET TIME OF LAST REAL MOVEM T1,PKTTIM(PKT) ; XMISSION FOR RE-XMISSION CHECKING LOAD T1,CPKNB,(PKT) ;GET BYTE COUNT ADDI T1,CHPKDT*4+1 ;PLUS HEADER AND ROUND UP LSH T1,-1 ;INPUT 16-BIT BYTES HRLZM T1,PKTCDR(PKT) ;STORE AND CLEAR CDR MOVEI T1,PKTCDR(PKT) ;POINT THERE MOVEI T2,DROUTR ;PUT ON OUTPUT READY LIST CALL DR11Q DR11WO ;WAKE UP MICROCODE OKSKD1 RETSKP ;WE ALWAYS SUCCEED ;PUT PACKET IN T1 ONTO END OF DR11 READY LIST IN T2 DR11Q: SETZ T4, EXCH T4,(T2) ;GET LIST AND ZERO JUMPE T4,[HRLI T4,(T1) ;IF PREVIOUSLY EMPTY, THIS IS HEAD AS WELL JRST .+2] HRRM T1,(T4) ;STORE PACKET AS CDR(LAST) HRRI T4,(T1) ;MAKE IT NEW LAST MOVEM T4,(T2) ;SAVE UPDATED LIST RET >;IFN CHDR11 SUBTTL PACKET INPUT CHIPKT: SKIPN CHAON ;IS NET FULLY ON? JRST [ ;NOPE IFN SMFLG,< CALL RELPKT > ;ON KS, FIRST GET RID OF THIS PACKET JRST CHARLD ] LOAD T2,CPKDA,(PKT) ;GET DESTINATION ADDRESS CAME T2,MYCHAD ;MATCHES MINE? JRST CHAPFW ;NO, FORWARD PACKET LOAD T2,CPKSA,(PKT) ;GET SOURCE ADDRESS CAME T2,MYCHAD ;FROM MYSELF (LOCALLY ROUTED)? AOS CHNPKI ;NO, COUNT NUMBER OF REAL PACKETS INPUT MOVEI T2,[ASCIZ /Byte count too large/] LOAD T3,CPKNB,(PKT) ;GET BYTE COUNT CAMLE T3,CHPMXC ;SEE IF WITHIN LEGAL RANGE JRST CHALOS ;NO, SEND A LOS BACK THEN SKIPGE (PKT) ;< SEE IF DATA OPCODE (>= 200) JRST CHIDAT ;YES, HANDLE DATA PACKET THEN MOVEI T2,[ASCIZ /Illegal opcode/] LOAD T3,CPKOP,(PKT) ;GET OPCODE CAIL T3,.COMAX ;WITHIN RANGE? SETZ T3, ;NO, HANDLE WITH LOS RESPONSE JRST @CHAHSO(T3) ;YES, GO HANDLE IT CHAHSO: CHALOS ;ZERO? CHIRFC ;.CORFC CHIOPN ;.COOPN CHICLS ;.COCLS CHIANS ;.COFWD CHIANS ;.COANS CHISNS ;.COSNS CHISTS ;.COSTS IGNPKT ;.CORUT CHILOS ;.COLOS CHALOS ;.COLSN IGNPKT ;.COMNT CHIDAT ;.COEOF ;FORWARDING CHAPFW: JUMPE T2,IGNPKT ;0 FOR DESTINATION, JUST FLUSH IT IFN ARPAF,< LOAD T2,CPKDS,(PKT) ;CHECK FOR BAD ADDRESS ON SUBNET CAILE T2,MAXSBN ;RANGE CHECK JRST IGNPKT ;OUT OF RANGE, DISCARD HLRZ T2,SBNRUT(T2) ;GET ROUTING METHOD CAIN T2,CHXLCL ;LOCAL SUBNET? JRST IGNPKT ;YES, DISCARD >;IFN ARPAF LOAD T2,CPKFC,(PKT) ;GET FORWARDING COUNT AOJ T2, CAIL T2,20 ;CHECK FOR FORWARDING LOOP JRST IGNPKT ;AND DISCARD IF SO STOR T2,CPKFC,(PKT) GETPKT ;GET PACKET COPY RET ;CANNOT DO THE COPY, PUNT AOS CHNPF ;ONE MORE PACKET FORWARDED SETO T1, ;DON'T BLOCK JRST CHAXMT ;AND GO SEND THIS PACKET OFF AGAIN ;RFC RECEIVED: SEE IF IT IS A DUPLICATE; IF NOT PUT ON LIST TO BE HANDLED. CHIRFC: MOVE T2,CHPKS(PKT) ;GET THE SOURCE OF THIS PACKET HLRZ T1,CHQRFC ;LOOK DOWN RFC LIST FOR POSSIBLE ONES JUMPE T1,CHIRF3 CHIRF1: CAMN T2,CHPKS(T1) ;FROM THE SAME SOURCE? JRST IGNPKT ;YES, JUST FORGET THIS NEW ONE HRRZ T1,PKTLNK(T1) ;GET THE NEXT IN LIST CAIE T1,-1 ;JUST IN CASE, MAKE SURE NOT EMPTY MARKER JUMPN T1,CHIRF1 SKIPE T1,CHQRFP ;FORK CODE HAVE HANDLE ON A PACKET? CAME T2,CHPKS(T1) ;YES, DOES IT MATCH? CAIA ;NOPE, SEE IF DUPLICATE CONNECTION JRST IGNPKT ;ELSE FLUSH DUPLICATE RFC CHIRF3: MOVSI T1,-MAXCON CHIRF4: SKIPL CONN,CHACON(T1) ;IS THERE A CONNECTION HERE? JRST CHIRF5 ;NO HRRZS CONN ;CLEAR UNIQUIZER CAMN T2,CHAFRN(CONN) ;THE SAME? JRST IGNPKT ;YES, FLUSH THIS DUPLICATE CHIRF5: AOBJN T1,CHIRF4 ;NO, KEEP LOOKING CALL CPYPKZ ;MAKE AN ASCIZ COPY OF THE PACKET JRST IGNPKT ;CANNOT MAKE COPY, PUNT SETZM PKTTIM(PKT) ;NOTE THAT WE'VE NOT SEEN IT YET MOVEI Q2,CHQRFC ;RFC RECEIVED LIST CALL CHAQPF ;ADD TO LIST MOVX T1,CH%RFC ;MARK ANOTHER RFC AS NEEDING HANDLING IORM T1,CHAFLG RET ;SNS RECEIVED CHISNS: CALL CHFNDX ;FIND OUR INDEX FOR THIS CONNECTION JRST CHALOS CAIE Q2,.CSOPN ;IS IT NOW OPEN? JRST IGNPKT ;NO, IGNORE REQUEST IFN SMFLG, ;ON KS10, RETURN SNS PACKET TO FREE POOL JRST CHASTO ;TRY TO SEND STATUS NOW FOR THIS CONNECTION ;STS RECEIVED CHISTS: CALL CHFNDX ;FIND CONNECTION JRST CHALOS CAIE Q2,.CSOPN ;MUST BE OPEN JRST CHALOS CHIST1: LDB T1,[POINT 16,CHPKDT(PKT),31] ;GET WINDOW SIZE FROM PACKET CAMLE T1,MXTWIN ;RANGE CHECK MOVE T1,MXTWIN JUMPLE T1,CHISTB CHIST2: HRRM T1,CHAWIN(CONN) ;STORE TRANSMIT WINDOW SIZE LDB T2,[POINT 16,CHPKDT(PKT),15] ;GET PACKET NUMBER BEING RECEIPTED CALL CHIAK0 ;REMOVE THOSE PACKETS FROM HIS LIST IFN SMFLG, ;ON KS, RETURN THE STS PACKET JRST CHARTR ;AND RETRANSMIT OTHERS LEFT ON IT FOR TOO LONG CHISTB: CHABUG(CHAZWN,<,>) ;NO, COMPLAIN MOVX T1,1 ;YES, SET IT TO MINIMUM JRST CHIST2 ;FWD OR ANS RECEIVED CHIANS: CALL CHFNDX ;FIND INDEX FOR THIS CONNECTION JRST IGNPKT ;NONE, NO CONN ON OTHER END TO TELL PRESUMABLY CAIN Q2,.CSRFS ;IN RFC-SENT STATE? JRST CHICL1 ;CLOSE CONNECTION, SETUP BUFFER W/ ERROR MESSAGE CAIE Q2,.CSPRF ;IN PERMANENT RFC-SENT STATE? JRST IGNPKT ;NO, JUST IGNORE IT CHIAN0: HRRZ T1,CHANBF(CONN) ;YES, GET NUMBER OF UNEATEN INPUT PACKETS HLRZ T2,CHAWIN(CONN) ;GET INPUT WINDOW SIZE CAIGE T1,(T2) ;IF WINDOW ISN'T FULL, GETPKT ; COPY PACKET INTO RESIDENT STORAGE IF NECESSARY RET ;WINDOW FULL OR CAN'T COPY, GIVE UP SKIPN CHAIBF(CONN) ;PREVIOUSLY EMPTY? CALL CHAIN1 ;YES, PERHAPS INTERRUPT AN INTERESTED FORK AOS CHANBF(CONN) ;ONE MORE ON INPUT LIST MOVEI Q2,CHAIBF(CONN) ;PUT IT ON THE IN-ORDER LIST CALL CHAQPL RET ;DONE ;OPN RECEIVED CHIOPN: CALL CHFNDX ;FIND CONNECTION JRST CHALOS CAIE Q2,.CSRFS ;MUST BE RFC SENT JRST IGNPKT ;ELSE JUST IGNORE IT LOAD T2,CPKPN,(PKT) ;GET PACKET NUMBER HRLM T2,CHAPKN(CONN) ;SETUP RECEIVE PACKET NUMBERS FOR CONNECTION MOVE T2,CHPKS(PKT) ;GET SOURCE MOVEM T2,CHAFRN(CONN) ;THAT IS FOREIGN HOST FOR CONNECTION CALL CHIST1 ;PROCESS WINDOW SIZE AND RECEIPT AS STS CALL CHASTO ;SEND BACK STATUS MOVEI Q2,.CSOPN ;STATE FOR CONNECTION NOW OPEN JRST CHAINT ;MAYBE WAKE UP SOME FORK ;LOS RECEIVED CHILOS: CALL CHFNDX ;TRY TO FIND CONNECTION JRST IGNPKT ;IGNORE IT IF NOT JUMPE Q2,IGNPKT ;OR IS CLOSED CAIN Q2,.CSPRF ;PERMANENT-RFC STATE? JRST CHIAN0 ;YES, JUST GIVE THIS PACKET TO THE FELLOW PUSH P,PKT ;SAVE INCOMING PACKET CALL CHALFO ;FREE UP OUTPUT BUFFERS POP P,PKT MOVEI Q2,.CSLOS ;PUT INTO LOS STATE JRST CHICL2 ;GIVE USER ERROR MESSAGE ;CLS RECEIVED CHICLS: CALL CHFNDX JRST CHALOS CAIN Q2,.CSPRF ;PERMANENT-RFC STATE? JRST CHIAN0 ;YES, JUST GIVE THIS PACKET TO THE FELLOW CAIE Q2,.CSOPN ;STATE SHOULD BE OPEN CAIN Q2,.CSRFS ;OR RFC SENT CHICL1: TDZA Q2,Q2 ;NEW STATE IS CLOSED JRST CHALOS CHICL2: CALL CHAINT ;MAYBE INTERRUPT SOMEBODY JUMPE CONN,IGNPKT ;IF THIS KILLED THE CONNECTION, FORGET PKT PUSH P,PKT ;SAVE INCOMING PACKET MOVEI Q2,CHAPBF(CONN) ;POINTER TO OUT OF ORDER PACKETS CALL CHALFR ;FREE THEM ALL HRRZS CHANBF(CONN) ;NO MORE ON THAT LIST POP P,PKT JRST CHIDT1 ;RETURN LOS PACKET AS DATA ;DATA PACKET RECEIVED CHIDAT: CALL CHFNDX JRST CHALOS CAIE Q2,.CSOPN ;MUST BE OPENED JRST CHALOS CALL CHIACK ;PROCESS THE ACKNOWLEDGEMENT FIELD HLRZ T2,CHAPKN(CONN) ;GET LAST PACKET GIVEN TO USER LOAD T1,CPKPN,(PKT) ; AND GET NEW PACKET'S NUMBER HLRZ T4,CHAWIN(CONN) ;GET WINDOW SIZE ADDI T4,(T2) ;FIGURE THE HIGHEST LEGAL PACKET NUMBER SUB T4,T1 TRNE T4,100000 ;IS THIS WITHIN THE WINDOW SIZE (T4 LEQ T1)? JRST [ CONPTH [20] ;NO, REMEMBER AND IGNORE THIS PACKET CALL CHINVT ; AFTER NOTING THAT THIS NVT MAY NEED ATTN JRST IGNPKT ] HRRZ T2,CHAIBF(CONN) ;ANY INPUT BUFFERS ASSOCIATED WITH THIS? JUMPN T2,[LOAD T2,CPKPN,(T2) ;YES, GET PACKET NUMBER FOR LAST ON LIST JRST .+2] HLRZ T2,CHAPKN(CONN) ;NO, GET LAST PACKET GIVEN TO USER CAIL T2,177777 ;INCREMENT THIS PACKET NUMBER TDZA T2,T2 ADDI T2,1 CAMN T1,T2 ;THIS THE NEXT PACKET IN THE SEQUENCE? JRST CHIDT1 ;YES, QUEUE IT ONTO THE END OF THE LIST SUB T2,T1 TRNN T2,100000 ;COMPARE MOD 2^16 JRST CHIDTD ;LAST SEEN GREATER, DISCARD DUPLICATE PKT MOVEI T3,0 ;AT FRONT OF LIST HLRZ Q2,CHAPBF(CONN) ;GET FIRST PACKET IN OUT OF ORDER LIST JUMPE Q2,CHIDT4 ;THIS IS THE FIRST CHIDT3: LOAD T2,CPKPN,(Q2) ;GET ITS PACKET NUMBER SUB T2,T1 JUMPE T2,CHIDTD ;SAME AS THIS NEW ONE, DISCARD TRNN T2,100000 JRST CHIDT4 ;T1 LESS, THIS IS WHERE IT GOES MOVE T3,Q2 ;T2 LESS, KEEP LOOPING HRRZ Q2,PKTLNK(T3) JUMPN Q2,CHIDT3 ;UNLESS REACHED END CHIDT4: GETPKT ;ELSE SAVE THE PACKET IF NECESSARY JRST [ CONPTH [21] CONPTH T1 ;REMEMBER THE PACKET NUMBER WHEN WE PUNTED RET ] ;CANNOT COPY, PUNT FOR NOW DEBUG,< PKTPTH [53] ;IF DEBUGGING, REMEMBER WHERE WE STARTED CONPTH [22] CONPTH T1 ; AND REMEMBER THE PACKET NUMBER AT THIS POINT >;DEBUG SKIPE T3 HRRM PKT,PKTLNK(T3) ;THREAD ONTO PREVIOUS PACKET SKIPN Q2 HRRM PKT,CHAPBF(CONN) ;THREAD ONTO BACK OF LIST SKIPN T3 HRLM PKT,CHAPBF(CONN) ;THREAD ONTO FRONT OF LIST HRRM Q2,PKTLNK(PKT) MOVSI T3,1 ADDM T3,CHANBF(CONN) ;ONE MORE ON OUT OF ORDER LIST RET ;HERE IF IT GOES ONTO THE END OF THE REGULAR LIST; T2/ PACKET NUMBER. CHIDT1: GETPKT ;MOVE PACKET INTO RESIDENT STORAGE IF NECESSARY JRST [ CONPTH [23] CONPTH T2 RET ] ;CANNOT DO THE COPY, PUNT PKTPTH [54] ;WHEN DEBUGGING, REMEMBER OUR ROOTS CONPTH [24] CONPTH T2 ;NOTE THIS PACKET NUMBER SKIPN CHAIBF(CONN) ;PREVIOUSLY EMPTY? CALL CHAIN1 ;WAKE UP FORK MAYBE CHIDT2: AOS CHANBF(CONN) ;ONE MORE ON IN ORDER LIST MOVEI Q2,CHAIBF(CONN) CALL CHAQPL ;PUT ONTO END OF LIST CHIDT9: HLRZ PKT,CHAPBF(CONN) ;GET TOP OF OUT OF ORDER LIST JUMPE PKT,CHINVT ;NO MORE, GO UPDATE NVT BUFFERS IF ANY LOAD T3,CPKPN,(PKT) ;GET ITS PACKET NUMBER CAIL T2,177777 TDZA T2,T2 ADDI T2,1 CAME T3,T2 ;IS THIS THE NEXT ONE TO GO? JRST CHINVT ;NO, SEE IF THIS BELONGS TO AN NVT CONPTH [25] CONPTH T3 MOVEI Q2,CHAPBF(CONN) CALL CHAQGF ;YES, PULL OFF OUT OF ORDER LIST JUMPE PKT,CHIDTB MOVSI T3,-1 ADDM T3,CHANBF(CONN) ;ONE LESS ON THAT LIST JRST CHIDT2 ;AND ONE MORE FOR IN ORDER LIST CHIDTB: CHABUG(CHAOOL) ;OUCH, NOT THERE NOW? COMPLAIN RET ; AND GET OUT ;HERE IF HAVE TO DISCARD A PACKET, ALSO SEND RECEIPT TO STOP RETRANSMISSION SOON CHIDTD: AOS CHANPD ;ONE MORE PACKET DISCARDED CONPTH [26] IFN SMFLG, ;ON KS, FREE UP THIS DISCARD JRST CHASTO ;AND GO MAKE SURE DO ACK ;IF THIS INPUT WAS FOR AN NVT, QUEUE UP THIS CONNECTION AS NEEDING ATTENTION CHINVT: LOAD T2,CHANVT,(CONN) ;GET NVT NUMBER CALL CHKCVT ;IS IT AN NVT? JRST CHINVR ;NOPE SETZ T3, ;EMPTY SLOT REF EVENTUALLY MOVEI T1,CHATTW ;SCAN Q FOR THIS CONNECTION CHNVT0: CAIL T1,CHATTW+NTTCVT ;CHECKED ALL OF Q? JRST CHNVT2 ;YES, GO STORE NEW ENTRY JUMPN T3,CHNVT1 ;ALREADY HAVE EMPTY SLOT MOVE T2,(T1) ;GET THIS ELEMENT CAMN T2,[-1] ;END OF Q MARKER? MOVEI T3,(T1) ;YES, REMEMBER IT CHNVT1: CAMN CONN,(T1) ;IS THIS CONNECTION ALREADY MARKED AS NEEDING HELP? JRST CHINVR ;YES, NOTHING TO DO AOJA T1,CHNVT0 ;NO, KEEP LOOKING CHNVT2: SKIPN T3 ;NON-ZERO MEANS FOUND A FREE SLOT CHABUG(CHNVBQ) ;WOW BAD Q: GIVE UP MOVEM CONN,(T3) ;STASH THIS NEW ELEMENT CHINVR: RET ;DONE ;HANDLE RECEIVED PACKET ACKNOWLEDGEMENT CHIACK: LOAD T2,CPKAN,(PKT) ;GET PACKET NUMBER BEING RECEIPTED CHIAK0: LOAD T3,CPKAN,(PKT) HRRZ T1,CHAACK(CONN) ;GET MAX OF THIS AND PREVIOUS ACKNOWLEDGED SUB T1,T3 TRNE T1,100000 HRRM T3,CHAACK(CONN) PUSH P,PKT HLRZ PKT,CHAOBF(CONN) ;GO DOWN CONNECTION SEND LIST JUMPE PKT,CHIAK2 CHIAK1: CHKPKT ;VALIDATE PACKET IF DEBUGGING LOAD T1,CPKOP,(PKT) ;GET OPCODE CAIE T1,.CORFC ;RFC OR CAIN T1,.COOPN ;OPN THAT WE ARE RETRANSMITTING? JRST CHIAK3 ;YES, CAN FLUSH IT NOW LOAD T1,CPKPN,(PKT) ;GET THIS PACKET'S NUMBER SUBM T2,T1 TRNE T1,100000 JRST CHIAK2 CHIAK3: HRRZ Q2,PKTLNK(PKT) ;GET NEXT PACKET HLLOS PKTLNK(PKT) ;MARK PKT AS NOT ON ANY SEND LIST RCALL RELPKM,14 ;RELEASE PACKET IF NOT BEING SENT NOW CHIAK4: HRLM Q2,CHAOBF(CONN) SKIPE PKT,Q2 JRST CHIAK1 ;KEEP TRYING REST OF SEND LIST SETZM CHAOBF(CONN) ;NOTHING ON SEND LIST NOW CHIAK2: MOVE T2,CHANOS(CONN) ;GET PREVIOUS STATE HRRZ T3,CHAACK(CONN) HRRZ Q2,CHAPKN(CONN) SUB T3,Q2 SKIPLE T3 SUBI T3,200000 ADD T3,CHAWIN(CONN) HRREM T3,CHANOS(CONN) JUMPG T2,CHIAK5 ;ALREADY HAD WINDOW? LOAD T1,CHAOCN,(CONN) SKIPLE CHANOS(CONN) ;AND SOME NOW? CAIL T1,^D36 JRST CHIAK5 ;SKIP IT MOVX T1,CF%OIN ;GENERATE OUTPUT INTERRUPT IORM T1,CHASTA(CONN) ;NOTE THIS NEED MOVX T1,CH%OIN ; AND TELL BACKGROUND FORK THERE'S WORK HERE IORM T1,CHAFLG CHIAK5: POP P,PKT RET ;FIND INDEX FOR THIS CONNECTION INTO CONN, STATE INTO Q2 CHFNDX: MOVEI T2,[ASCIZ /Connection does not exist at this end/] ;HANDY MESSAGE LOAD CONN,CPKD1,(PKT) ;GET DESTINATION INDEX CAIGE CONN,MAXCON ;WITHIN RANGE SKIPL CONN,CHACON(CONN) ;AND IN USE RET ;NO, FAIL HRRZS CONN ;CLEAR OUT UNIQUIZER CHKCON ;VALIDATE IT IF DEBUGGING, REGARDLESS OF OUTCOME HRRZ Q2,CHASTA(CONN) MOVE T1,CHPKS(PKT) MOVE T3,CHPKD(PKT) CAIN Q2,.CSRFS ;IF IN RFC SENT, DONT CARE ABOUT INDEX AND T1,[BYTE (16) -1, 0] CAMN T3,CHALCL(CONN) ;LOCAL AND CAME T1,CHAFRN(CONN) ;FOREIGN THE SAME? RET ;NO, NO GOOD MOVE T1,TODCLK MOVEM T1,CHAITM(CONN) ;TIME OF LAST INPUT ON THIS CONNECTION MOVEI T2,[ASCIZ /Connection not in right state at this end/] RETSKP ;OK, BUT HANDY MESSAGE IN T2 IF ANYONE NEEDS IT SUBTTL PACKET MUNGING SUPPORT ;GET STORAGE FOR PACKET, OPCODE IN Q2; WHEN DEBUGGING, REASON IS IN CX ASGPKI: ADD T1,[.RESP1,,CHPKDT+PKTHLN] ;ASSIGN A PACKET AT INTERRUPT LEVEL JRST ASGPK2 ; WITH LENGTH IN T1 ASGPK0: TDZA T1,T1 ;NO DATA NEEDED ASGPKC: MOVE T1,CHPMXW ;MAXIMUM NUMBER OF WORDS OF DATA ASGPK1::ADD T1,[.RESP3,,CHPKDT+PKTHLN] ;PACKET HEADER PLUS HEADER WORDS ASGPK2: MOVEI T2,.RESNP ;FROM THE NETWORK POOL DEBUG,< PUSH P,CX > ;SAVE REASON CODE (FOR WHEN DEBUGGING) CALL ASGRES JRST [ DEBUG, ;IF DEBUGGING, FLUSH REASON RET ] ;FAIL RETURN MOVEI PKT,PKTHLN(T1) ;RETURN ADDRESS OF PACKET IN PKT SETOM PKTLNK(PKT) ;NOT ON ANY TRANSMIT QUEUES YET MOVE T1,TODCLK ;SET IN PACKET-CREATION TIME MOVEM T1,PKTTIM(PKT) STOR Q2,CPKOP,(PKT) ;SET IN OPCODE GIVEN DEBUG,< MOVE T1,[CHSMGV] ;BUILD MAGIC VALUE XORI T1,(PKT) ; KEYED TO CURRENT PACKET MOVEM T1,PKTMAG(PKT) ;SET IT MOVE T1,-PKTHLN-1(PKT) ;GET ASGRES HEADER WORD MOVEM T1,PKTHDW(PKT) ;SAVE IT HERE FOR DUAL-CHECKING MOVEI T1,PKTHST(PKT) ;BUILD BYTE REF TO HISTORY TRAIL HRLI T1,360600 ; (DPB REF) POP P,T2 ;PICK UP ASSIGN-PACKET REASON DPB T2,T1 ; AND DROP IT IN IBP T1 ;BUMP AND MOVEM T1,PKTHSP(PKT) ; SAVE REF >;DEBUG RETSKP IFN SMFLG,< ;ON KS, MAKE COPY OF PACKET ONLY IF HAVE TO; T3/ BYTE COUNT. ;ONCE COPIED, WE FREE ORIGINAL. CPYPKI: SAVET LOAD T1,CPKNB,(PKT) ;GET BYTE COUNT CAML T1,T3 ;IF PACKET IS BIG ENOUGH RETSKP ; JUST RETURN IT MOVE T1,T3 ;ELSE, GET NUMBER OF BYTES WE NEED PUSH P,PKT ;SAVE ORIGINAL PACKET REF CALL CPYPK1 ;DO THE WORK CAIA AOS -1(P) ;MIMIC SUCCESS EXCH PKT,(P) ;GET ORIGINAL PACKET AND SAVE NEW REF CALL RELPKT ; AND FREE UP ORIGINAL POP P,PKT ;GET BACK NEW PACKET REF RET ;RETURN SUCCESS OR FAILURE >;IFN SMFLG, ;MAKE A COPY OF THE PACKET IN PKT IN RESIDENT STORAGE, ;SINCE IT IS JUST A DTE BUFFER NOW. NON-SKIP RETURN ON FAILURE. CPYPKT: SAVET ;SAVE TEMP ACS LOAD T1,CPKNB,(PKT) ;GET BYTE COUNT CPYPK1: ADDI T1,3 ;ROUND TO WORD LSH T1,-2 ;TURN INTO INTO WORDS PUSH P,T1 ;SAVE SIZE PUSH P,PKT ; AND ORIGINAL PACKET REF RCALL ASGPKI,37 ;GET A PACKET FROM INTERRUPT-LEVEL POOL JRST [ AOS CHNNRS ;JUST COUNT THESE NOW: PERFECTLY NORMAL JRST CPYPK9 ] MOVE T3,-1(P) ;GET BACK SIZE OF ORIGINAL PACKET'S DATA IN WORDS ADDI T3,CHPKDT-1(PKT) ; AND REF TO END OF NEW PACKET HRL T2,(P) ;GET BACK ORIGINAL PACKET REF AS SOURCE,, HRRI T2,(PKT) ; THEN ADD DESTINATION BLT T2,(T3) ;MOVE DATA AOS -2(P) ;INDICATE WINNAGE (ISN'T OBSCURITY WONDERFUL?) CPYPK9: ADJSP P,-2 ;FLUSH TWO TEMPS RET ;GET OUT; SKIP OR NON-SKIP ALREADY SET ;MAKE A COPY WITH AN ASCIZ CONTACT NAME; ON KS, ORIGINAL PACKET IS FREED UP, ;UNLESS THE COPYING FAILS. CPYPKZ: LOAD T1,CPKNB,(PKT) ;GET BYTE COUNT PUSH P,T1 ;SAVE FOR LATER IFN SMFLG, ;SAVE THIS PACKET REF, TOO, ON KS AOJ T1, ;MAKE ROOM FOR THE NULL CALL CPYPK1 ;GO DO THIS SIZE COPY THEN JRST [ ADJSP P,-1 ;MIMIC FAILURE, FLUSHING TEMPS ON THE WAY IFN SMFLG,< POP P,PKT> RET] IFN SMFLG,< ;ON KS, HAVE TO FLUSH OLD PACKET EXCH PKT,(P) ;SAVE AND GET OLD PACKET CALL RELPKT ;GET RID OF IT POP P,PKT ;GET BACK COPY REF >;IFN SMFLG, POP P,T1 ;GET BACK COUNT IFN KLFLG!SMFLG,< ADJBP T1,[POINT 8,CHPKDT(PKT)] > ;REF LAST BYTE IFN F3FLG,< IDIVI T1,4 ;BYTES PER WORD ADD T1,[POINT 8,CHPKDT(PKT)] SOJL T2,.+3 IBP T1 JRST .-2 >;IFN F3FLG, MOVEI T2,0 IDPB T2,T1 ;APPEND A NULL TO IT RETSKP ;TOTALLY IGNORE AN INPUT PACKET (WHICH, ON THE KS, IS A FULL-BLOWN PACKET, AS ;ALL ARE, AND ON OTHER SYSTEMS, IS A VESTIGIAL PACKET WHICH DOESN'T NEED ;ANY FURTHER HANDLING). IGNPKT: IFE SMFLG, ;NOOP ON NON-KS IFN SMFLG, ;KS NEEDS TO FREE IT UP ;RELEASE A PACKET IF IT IS NOT RETRANSMITTABLE (IE, IF NOT TRANSMITTING OR ;QUEUED UP FOR OURSELVES, AND NOT ON ANY LISTS NOW, AS INDICATED BY ITS ;LINK WORD). IF DEBUGGING, THE REASON CODE IS IN CX. ;CALL RELPKT WHEN YOU EXPECT THE PACKET TO BE FREEABLE RIGHT NOW. RELPKT:: DEBUG,< PUSH P,T1 MOVE T1,PKTLNK(PKT) ;PICK UP LINK WORD CAME T1,[-1,,-1] ;FREEABLE NOW? CHABUG(CHANFP,<>) ;NO, COMPLAIN POP P,T1 ;GET BACK TEMP AND FALL INTO RELPKM >;DEBUG RELPKM::PUSH P,T1 ;SAVE TEMPS CHKPKT ;CHECK PACKET IF DEBUGGING MOVE T1,PKTLNK(PKT) ;GET XMIT-ACTIVE FLAG,,LINK HALF-WORD CAME T1,[-1,,-1] ;IF EITHER ACTIVE OR QUEUED LOCALLY OR ON A LIST JRST RELPKD ; THEN DON'T BOTHER IT: WILL GET FREED LATER PUSH P,T2 ;SAVE FURTHER TEMPS NOW THAT WE HAVE WORK TO DO PUSH P,T3 PUSH P,T4 DEBUG,< MOVEI T3,(CX) ;GET REASON CODE MOVEM T3,PKTMAG(PKT) ;CLEAR OUT MAGIC AND SET IN REASON FOR RELEASE PKTPTH T3 ;SET THIS IN ITS HISTORY, TOO >;DEBUG MOVEI T1,-PKTHLN(PKT) ;POINT TO START OF ACTUAL BLOCK FOR RELRES SETZ PKT, ;INDICATE GONE CALL RELRES ;RELEASE IT POP P,T4 ;GET BACK TEMPS POP P,T3 POP P,T2 RELPKD: POP P,T1 RET ;SEND BACK A LOS FOR PACKET REF'ED BY PKT; ASCIZ REF TO REASON IN T2 CHALOS: SKIPA T1,[.COLOS] CHALS2: MOVEI T1,.COCLS ;RECEIVED A LOSING RFC MOVEI T3,100 GETPKT T ;JUST A DTE BUFFER OR RFC PKT THAT WE SHOULD COPY RET ;CAN'T? JUST IGNORE IT THEN PKTPTH [55] STOR T1,CPKOP,(PKT) ;SETUP OPCODE FIELD MOVE T1,CHPKS(PKT) ;EXCHANGE SOURCE AND DESTINATION EXCH T1,CHPKD(PKT) MOVEM T1,CHPKS(PKT) CALL PKTSTR ;PUT THE ASCIZ STRING FROM T2 INTO THE DATA PORTION SETO T1, JRST CHAXMT ; OF THE PKT AND GO ACTUALLY SEND IT PKTSTR: SETZ T3, ;EVENTUAL COUNT TLNN T2,-1 ;MIGHT BE AN 8-BIT BYTE POINTER ALREADY HRLI T2,() MOVE T1,[POINT 8,CHPKDT(PKT)] PKTST1: ILDB Q2,T2 CAIN Q2,"_" MOVEI Q2," " ;CONVERT _'S TO SPACES IN CONTACT NAMES IDPB Q2,T1 JUMPE Q2,PKTST2 AOJA T3,PKTST1 PKTST2: STOR T3,CPKNB,(PKT) ;SETUP BYTE COUNT RET ;SEND A STS PACKET OR MARK FOR NETWORK FORK TO DO IT CHASTO: MOVEI T1,1 ;JUST NEED 4 BYTES OF DATA (1 WORD) MOVEI Q2,.COSTS RCALL ASGPKI,40 ;GET PACKET FROM INTERRUPT POOL JRST [ MOVX T1,CF%STS ;FAILED: IORM T1,CHASTA(CONN) ;MARK THIS ONE AS NEEDING STS MOVX T1,CH%STS ;AND TELL CHAOS FORK THERE'S ANOTHER TO HANDLE IORM T1,CHAFLG RET ] CHSTO2: MOVEI T1,4 ;FOUR BYTES OF DATA STOR T1,CPKNB,(PKT) HLRZ T1,CHAWIN(CONN) DPB T1,[POINT 16,CHPKDT(PKT),31] ;PUT IN THE RECEIVE WINDOW SIZE HLRZ T2,CHAPKN(CONN) ;GET LAST PACKET SEEN BY USER HRRZ T1,CHAIBF(CONN) SKIPE T1 LOAD T2,CPKPN,(T1) ;OR THAT GOT INTO THE IN-ORDER QUEUE DPB T2,[POINT 16,CHPKDT(PKT),15] ;STORE AWAY AS RECEIPT PACKET NUMBER CONPTH [30] ;WHEN DEBUGGING, REMEMBER WE SEND THIS STS CONPTH T2 AOS CHNSTS ;ONE MORE STS SENT SETO T1, CALLRET SNDPK0 ;AND HANDLE LIKE DATA (BUT DON'T BLOCK FOR IT) ;SEND STS OR OPN PACKET FROM PROCESS LEVEL SWAPCD CHASO1: MOVEI Q2,.COSTS CHASO2: HRRZ T1,CHASTA(CONN) ;MAKE SURE STILL WORTH DOING CAIE T1,.CSOPN RET ;NOPE, JUST IGNORE MOVEI T1,1 ;(ENTER HERE WITH Q2/ OPCODE) ONE WORD OF DATA RCALL ASGPK1,41 ;GET A PACKET FOR THIS CONNECTION RET ;FAILED, LET NORMAL MECHANISMS DO IT LATER MOVX T1,CF%STS ;NOTE WE'VE HANDLED THIS NEED FOR STATUS ANDCAM T1,CHASTA(CONN) JRST CHSTO2 ;GO SEND IT OFF RESCD ;RETRANSMIT ANYTHING LYING AROUND FOR TOO LONG FOR THIS CONNECTION. CHARTR: HRRZ T1,CHASTA(CONN) ;MAKE SURE STILL IN VALID STATE FOR RETRANSMISSION CAIE T1,.CSOPN CAIN T1,.CSRFS CAIA RET HLRZ PKT,CHAOBF(CONN) ;IS THERE ANY WORK HERE? JUMPE PKT,R ;NO DEBUG,< PUSH P,Q2 ;COUNT OF PACKETS RE-XMITTED SETZ Q2, ; FOR DEBUGGING >;DEBUG CALL NOSKDP ;PREVENT TAMPERING WITH QUEUE SETZ T1, ;LAST PACKET NUMBER WE RE-XMITTED CHART1: HLRZ PKT,CHAOBF(CONN) CAIA CHART2: HRRZ PKT,PKTLNK(PKT) JUMPE PKT,CHARTD ;NO MORE, DONE CHKPKT LOAD T2,CPKPN,(PKT) ;GET PACKET NUMBER SUBM T1,T2 TRNN T2,100000 JRST CHART2 ;ALREADY RETRANSMITTED, TRY NEXT MOVE T1,PKTTIM(PKT) ;TRANSMIT TIME ADDI T1,^D33 ;DON'T RETRANSMIT IF SENT IN LAST 30TH SEC HLRZ T2,PKTLNK(PKT) ;XMIT ACTIVE FLAG CAMGE T1,TODCLK CAIE T2,-1 ;IF -1, NOTHING GOING ON WITH IT (ELSE, COULD BE ; XMIT ACTIVE, OR ROUTED TO OURSELVES LOCALLY) JRST CHARTD ;FORGET IT IF TOO SOON, OR ALREADY BEING XMITTED PKTPTH [50] LOAD T1,CPKPN,(PKT) ;SAVE PACKET NUMBER PUSH P,T1 SETO T1, CALL CHAXMT ;REXMIT IT WITHOUT BLOCKING SKIPE T1 ;DID IT GET SENT? AOS CHNRTR ;YES, ONE MORE RETRANSMISSION DEBUG,< AOS Q2 > POP P,T1 ;GET BACK PACKET NUMBER JRST CHART1 ;HERE WHEN DONE WITH RETRANSMISSION: UNLOCK AND GET OUT CHARTD: CALL OKSKDP ;DONE DEBUG,< CONPTH [31] CONPTH Q2 POP P,Q2 >;DEBUG RET ;SEE ABOUT TELLING SOMETHING THAT THERE HAS BEEN A STATE CHANGE ;FOR THIS CONNECTION: ; Q2/ NEW CONNECTION STATE ;RETURNS ; CONN/ 0 IF IT HAS BEEN ESSENTIALLY FLUSHED, ELSE NOT CHANGED CHAINT: HRRM Q2,CHASTA(CONN) ;SAVE NEW CONNECTION STATE CONPTH [32] CONPTH Q2 MOVE T1,TODCLK MOVEM T1,CHAITM(CONN) ;SET LAST INPUT ACTIVITY FOR THIS CONNECTION LOAD T2,CHANVT,(CONN) CAIE Q2,.CSOPN ;IS THIS ANY STATE OTHER THAN OPENED? CALL CHKCVT ;AND ASSOCIATED WITH AN NVT? JRST CHAIN1 ;NO, SEE IF THERE IS A FORK TO INTERRUPT MOVX T1,CF%DIN ;YES, TELL CHAOS FORK TO DO DETACH AND FLUSH IORM T1,CHASTA(CONN) MOVX T1,CH%DIN IORM T1,CHAFLG ;AND NOTE A DETACH INTERRUPT REQUEST PENDING SETZ CONN, ;TELL CALLER CONNECTION IS ESSENTIALLY FLUSHED RET CHAIN1: LOAD T1,CHAICN,(CONN) ;GET INTERRUPT CHANNEL CAIL T1,^D36 RET MOVX T1,CF%IIN ;MARK THIS CONNECTION AS NEEDING AN IORM T1,CHASTA(CONN) ; INPUT INTERRUPT MOVX T1,CH%IIN IORM T1,CHAFLG ;TELL BACKGROUND FORK ABOUT IT, TOO RET ;SEND A DATA PACKET ON CONNECTION IN CONN; RETURNS NONSKIP ON FAILURE SNDPKT: HRRZ T1,CHASTA(CONN) ;GET CONNECTION STATUS CAIE T1,.CSOPN ;OPENED? JRST SNDPKE ;NO, COMPLAIN AND FAIL SKIPLE CHANOS(CONN) ;ROOM WITHIN WINDOW SIZE? JRST SNDPKW ;YEP, GO ON MOVE T1,TODCLK ;NO, REMEMBER WHEN WE BLOCKED MOVEM T1,CHAOTM(CONN) MOVSI T1,(CONN) ;BLOCK UNTIL ROOM APPEARS HRRI T1,SNPKBT NOINT ;CANCEL OUT NOINT GIVEN ON UNLDIS IFN T20FLG,< CALL UNLDIS ;WAIT FOR IT, LOCKED >;IFN T20FLG IFN TNXFLG,< CALL UNLCKF MDISMS >;IFN TNXFLG HRRZ T1,CHASTA(CONN) ;CONNECTION CAIN T1,.CSOPN ; STILL IN VALID STATE? JRST SNDPKW ;YES, GO ON, REGARDLESS OF WINDOW STATE SNDPKE: RCALL RELPKM,15 ;RELEASE THE PACKET IF NOT OPEN RETBAD(CHAOX2) ;AND RETURN ERROR SNDPKW: AOS (P) ;CAN'T FAIL FROM THIS POINT ON; RETURN SUCCESS SETZ T1, ;BLOCKING IS OK FROM HERE ;SEND A DATA PACKET WITHOUT CHECKING CONNECTION STATUS OR AVAIL XMIT WINDOW; ;RETURNS NON-SKIP ALWAYS. T1/ NON-ZERO MEANS DON'T BLOCK. SNDPK1::HRRZ T2,CHAPKN(CONN) ;GET NEXT PACKET NUMBER TO USE CAIL T2,177777 TDZA T2,T2 ADDI T2,1 HRRM T2,CHAPKN(CONN) STOR T2,CPKPN,(PKT) ;LIKE SNDPK1, BUT DON'T WORRY ABOUT PACKET NUMBER (EG, FOR SNS PACKETS) SNDPK0: MOVE T4,T1 ;SAVE BLOCKING-OK ARG DEBUG,< MOVE T1,PKTLNK(PKT) ;MAKE SURE THIS PACKET HAS NO STRINGS ATTACHED CAME T1,[-1,,-1] ;SHOULD BE TOTALLY VANILLA CHABUG(CHASPS,<,>) ;OOPS >;DEBUG HLRZ T1,CHAPKN(CONN) ;PACKET NUMBER TO ACKNOWLEDGE HRLM T1,CHAACK(CONN) ;REMEMBER WE DID SO STOR T1,CPKAN,(PKT) ;FILL IN ACK FIELD SETZRO CPKFC,(PKT) ;CLEAR FORWARDING COUNT MOVE T1,CHALCL(CONN) MOVEM T1,CHPKS(PKT) ;SOURCE MOVE T1,CHAFRN(CONN) MOVEM T1,CHPKD(PKT) ;DESTINATION LOAD T1,CPKOP,(PKT) ;GET THE OPCODE CAIE T1,.CORFC ;RFC AND OPN GET RETRANSMITTED CAIN T1,.COOPN JRST SNDPK2 ; BUT DON'T COUNT TOWARD THE WINDOW CAIN T1,.COEOF ;AS DOES EOF JRST SNDPK4 CAIGE T1,.CODAT ; OR DATA JRST SNDPK3 ;NO, GUESS ONLY SEND IT ONCE THEN SNDPK4: SOSGE CHANOS(CONN) ;ONE LESS AVAILABLE WINDOW SLOT (DATA AND EOF ONLY) SETZM CHANOS(CONN) ;DON'T LET IT DROP BELOW ZERO, THOUGH SNDPK2: MOVEI Q2,CHAOBF(CONN) ;PUT ONTO END OF SEND LIST CALL NOSKDP ;HAVE TO LOCK UP JUST IN CASE IT'S ILLEGALLY CALL CHAQPL ; ACKED BEFORE WE EVEN GET AROUND TO XMITTING IT XMOVEI T1,OKSKDP ;***KLUDGE*** UNLOCK WHEN LEAVING PUSH P,T1 SNDPK3: MOVE T1,T4 ;GET BACK BLOCKING-OK ARG DEBUG,< CALL CHAXMT ;SEND THIS PACKET OFF, WHEN DEBUGGING CONPTH [34] CONPTH T1 ;REMEMBER WHAT HAPPENED RET >;DEBUG ;SEND THE PACKET IN PKT; T1/ NON-ZERO MEANS JUST RETURN IF NEED TO BLOCK; ;RETURNS T1/ NON-ZERO IFF SHIPPED THE PACKET OFF SOMEWHERE. CHAXMT: STKVAR MOVEM T1,CHXMNB ;SAVE ARGUMENT CHKPKT ;CHECK PACKET IF DEBUGGING PKTPTH [51] MOVE T1,TODCLK ;SET TIME OF LAST TRANSMISSION, EVEN IF WE DON'T MOVEM T1,PKTTIM(PKT) ; XMIT IT RIGHT AWAY, FOR CHECKING PURPOSES CALL CHXRUT ;FIND OUT HOW IT'S GOING TO BE SENT MOVEM T2,CHXRTM ;REMEMBER IFN DTEFLG,< CAIE T2,CHXDTE ;IF NOT THROUGH FE-11, JRST CHAXM1 ; DON'T WORRY ABOUT -11 STATUS SKIPL CHNPO1 ;TOO MANY PACKETS OUTSTANDING IN -11? CONSZ PI,177B27 ;OR PI IN PROGRESS? JRST CHAXM1 ;NO, ROOM EXISTS, OR AT PI LEVEL, GO ON SKIPN INSKED ;IF WE ARE IN THE SCHEDULER SKIPE NSKED ;OR CANNOT GO BLOCKED JRST CHAXM1 ;SEND IT ANYWAY SETZ T1, ;ASSUME NOT OK EXCH T1,CHXMNB ;OK TO BLOCK? (SAY WE DIDN'T SEND, IF NOT) JUMPN T1,CHXDN1 ;NOPE, GET OUT MOVEI T1,CHXMTT ;ELSE WAIT FOR ROOM HRLI T1,(PKT) ;PACKET REF IS DATA TO CHXMTT FOR TIMEOUT CHECK NOINT ;CANCEL OUT OKINT GIVEN IN UNLDIS CALL UNLDIS ;WAIT FOR ROOM TO APPEAR IN -11 PKTPTH [52] ;REMEMBER WE WAITED FOR IT >;IFN DTEFLG CHAXM1: SETZM CHXMNB ;ASSUME THE WORST ABOUT SENDING THE PACKET CALL NOSKDP ;LOCK UP HERE SO WE DON'T SEND AN XMIT-ACTIVE PKT CHKPKT ;MAKE SURE THIS PACKET IS STILL OK AFTER WAITING HLRZ T1,PKTLNK(PKT) CAIE T1,-1 ;MUST BE TOTALLY QUIESCED FOR US TO DEAL W/IT JRST CHXDON ;YEP, ALREADY ACTIVE IN SOME WAY, SO FORGET IT MOVSI T1,1 HLLM T1,PKTLNK(PKT) ;FLAG XMIT ACTIVE NOW MOVE T2,CHXRTM ;GET ROUTING METHOD CALL (T2) ;CALL THE ROUTER WE'VE CHOSEN JRST [ HRROS PKTLNK(PKT) ;FAILED: NO LONGER XMIT ACTIVE, REMEMBER THAT PKTPTH [56] ;(NOTE FAILURE WHEN DEBUGGING) JRST CHXDON ] ; AND RETURN "NOT SENT" SETOM CHXMNB ;ELSE, SAY WE'VE SENT THIS PACKET CHXDON: CALL OKSKDP ;UNLOCK CHXDN1: SKIPE T1,CHXMNB ;FIND OUT IF WE ACTUALLY SENT THIS PKT OR NOT RET ;YES, ALL DONE RCALL RELPKM,22 ;ELSE, THIS GUY WASN'T QUEUED TO GO, SO IF IT'S RET ; NO LISTS, GET RID OF IT SUBTTL SNDPKT SUPPORT ROUTINES ;WAIT FOR ROOM TO APPEAR IN THE FE -11 CHXMTT::SKIPE CHAON ;NET STILL UP? SKIPGE CHNPO1 ;ANY ROOM IN -11? JRST 1(T4) ;NO, OR YES, UNBLOCK TO DISCOVER THE TRUTH TCHKPK ;CHECK THIS PACKET REF IF DEBUGGING MOVE T2,PKTTIM(T1) ;NET UP, AND NO ROOM IN -11, GET TIME OF XMIT START ADDI T2,^D<5*1000> ;IF WE'RE WAITING ON THE -11 FOR THIS LONG CAMG T2,TODCLK JRST CHXMTB JRST 0(T4) ;KEEP WAITING CHXMTB: CHABUG(CHAXOD) ;SOMETHING'S PROBABLY WRONG: COMPLAIN MOVE T2,TODCLK ;AND RESET THE TIME SO WE WON'T COMPLAIN TOO MUCH MOVEM T2,PKTTIM(T1) JRST 0(T4) ;DTEQ PACKET SENT TO -11 OK; IF IT ISNT ON ANY TRANSMIT LIST, IT CAN BE ;DEALLOCATED CHAXIN: IFE SMFLG, ;ON KS, PKT IS ALREADY PROPERLY SET UP PKTPTH [61] ;NOTE WE GOT HERE WHEN DEBUGGING DEBUG,< PUSH P,T2 HLRZ T1,PKTLNK(PKT) ;PICK UP XMIT ACTIVE FLAG MOVE T2,PKTMAG(PKT) ;GET MAGIC FIELD IF DEBUGGING CAIE T1,1 ;BETTER BE WHAT WE LEFT IT AT CHABUG(CHAXIB,<,,>) ;NO, COMPLAIN >;DEBUG HRROS PKTLNK(PKT) ;CLEAR TRANSMIT ACTIVE RCALL RELPKM,16 DEBUG,< POP P,T2 > RET ;SCHEDULER TEST FOR WINDOW TO OPEN UP ON A CONNECTION SNPKBT: TCHKCN ;IF DEBUGGING, CHECK CONNECTION HRRZ T2,CHASTA(T1) ;GET STATE OF CONNECTION CAIE T2,.CSOPN ;VERIFY STILL OPENED JRST 1(T4) SKIPLE CHANOS(T1) ;ANY WINDOW AVAILABLE? JRST 1(T4) ;YES, UNBLOCK MOVE T2,TODCLK ;NO, GET NOW SUB T2,CHAOTM(T1) ;FIND OUT HOW LONG WE'VE BEEN WAITING CAIL T2,^D<10*1000> ;IF OVER SOME RATHER LONG TIME, JRST 1(T4) ; UNBLOCK TO SEND OVER WINDOW JRST 0(T4) ;ELSE, KEEP WAITING SUBTTL ROUTING SUPPORT ;CHOOSE A ROUTING METHOD; RETURNS T2/ ROUTINE TO USE CHXRUT: SETZ T2, ;ASSUME NORMAL (THROUGH FE -11) ROUTING IFN ARPAF,< ;166 LOAD T1,CPKDS,(PKT) ;GET DESTINATION SUBNET CAIG T1,MAXSBN ;RANGE CHECK HLRZ T2,SBNRUT(T1) ;OK, GET ROUTING METHOD > LOAD T1,CPKDA,(PKT) ;BUT ALSO CHECK DESTINATION HOST ADDRESS CAMN T1,MYCHAD ;IS IT I? MOVEI T2,CHXLCL ;YES, SEND LOCALLY SKIPN T2 ;ANY ROUTING CHOSEN YET? MOVEI T2,CHXNOR ;NO, GO THROUGH NORMAL ROUTE TLZ T2,-1 ;MAKE SURE NO SECTION FUNNINESSES RET ;ROUTE TO OURSELVES; DON'T EVEN HACK ANY HARDWARE (LET BACKGROUND FORK DO IT) CHXLCL: AOS CHNPOL ;COUNT THIS LOCAL ROUTING PKTPTH [57] HRRZS PKTLNK(PKT) ;THIS WILL BE THE END OF LOCAL-Q LIST HRRZ T1,CHQLCL ;GET CURRENT TAIL HRRM PKT,CHQLCL ; AND MAKE THIS THE NEW TAIL JUMPN T1,[HRLM PKT,PKTLNK(T1) ;IF NON-NIL OLD TAIL, MAKE IT REF NEW TAIL JRST .+2] HRLM PKT,CHQLCL ;ELSE, WAS EMPTY, ON BOTH ENDS, MAKE IT TAIL, TOO RETSKP ;NO PROBLEMS IFN DTEFLG,< ;ROUTE NORMALLY THROUGH THE (PRIMARY OR SECONDARY) FRONT END CHXNOR: CHXDTE: SKIPN CHAON ;IF NETWORK ISN'T UP, RET ; THIS IS FUTILE, FAIL RETURN AOS CHANPO ;ONE MORE PACKET REALLY OUTPUT TO -11 AOSLE CHNPO1 ;ONE MORE PACKET OUTSTANDING IN -11 JRST [ SETZM CHNPO1 ;OOPS, WENT TOO FAR: PUT IT BACK AOS CHANOL ;COUNT OVERESTIMATIONS RET ] ; AND FAIL RETURN TO SAY WE DIDN'T SEND IT PKTPTH [60] ;REMEMBER WE'VE BEEN HERE MOVE T1,TODCLK ;SET TIME OF LAST REAL MOVEM T1,PKTTIM(PKT) ; XMISSION FOR RE-XMISSION CHECKING PUSH P,F MOVEI F,(PKT) ;UNIQUE CODE IS PACKET POINTER MOVSI A,CHAXIN ;WHERE TO GO WHEN -11 GETS IT LOAD C,CPKNB,(PKT) ;BYTE SIZE IFE CHADTE,< ADDI C,CHPKDT*4+3 ;PLUS PACKET HEADER TRZ C,3 ;MAKING EVEN NUMBER OF WORDS MOVE B,[.DFHSD,,.FECHA] MOVEI D,(PKT) HRLI D,() >;IFE CHADTE IFN CHADTE,< ADDI C,*4+3 ;PLUS PACKET HEADER AND INTERNAL HEADER TRZ C,3 ;MAKING EVEN NUMBER OF WORDS LSH C,-1 ;MAKE 16 BIT BYTE COUNT HRRI A,CHADTE ;DTE NUMBER TO SEND TO MOVEI B,PKTTYP(PKT) SETZM (B) ;CLEAR TYPE FIELD HRLI B,() >;IFN CHADTE CALL DTEQ SKIPA ;I GUESS WILL RETRANSMIT SOMETIME SOON IF NECESSARY AOS -1(P) ;WORKED: RETURN SUCCESS POP P,F RET >;IFN DTEFLG IFN ARPAF,< ;ROUTING TABLE: ROUTING ROUTINE,,GATEWAY HOST (IF ANY) SBNRUT: CHXNOR,,0 ;SUBNET 0, NOT USED CHXDTE,,0 ;SUBNET 1, MAIN CAMPUS LOOP CHXDTE,,0 ;SUBNET 2, ETHERNET CHXDTE,,0 ;SUBNET 3, MC CHXDTE,,0 ;SUBNET 4, AI CHXDTE,,0 ;SUBNET 5, XX CHXDTE,,0 ;SUBNET 6, 9TH FLOOR OF TECH SQUARE CHXNOR,,0 ;SUBNET 7, NOT USED CHXDTE,,0 ;SUBNET 10, LCSNET CHXIMP,,0 ;SUBNET 11, ARPANET 0 ;SUBNET 12, NOT USED CHXDTE,,0 ;SUBNET 13, EECS REPEAT 4,<0> ;SUBNETS 14-17 NOT USED REPEAT 14, ;SUBNETS 20-33, LLL REPEAT 4,<0> ;SUBNETS 34-37 NOT USED MAXSBN==.-SBNRUT-1 ;ROUTE TO SUBNET THROUGH ARPANET HOST CHXIMI: LOAD T1,CPKDS,(PKT) ;GET DESTINATION SUBNET SKIPA T1,SBNRUT(T1) ;GET GATEWAY ADDRESS FOR THAT CHXIMP: LOAD T1,CPKDA,(PKT) ;GET DESTINATION ADDRESS HRLZM T1,PKTIMP(PKT) ;SAVE AWAY FIRST STEP DESTINATION PIOFF HLRZ T1,CHARPQ ;END OF ARPANET QUEUE JUMPE T1,[HRRM PKT,CHARPQ ;HEAD OF QUEUE TOO IF EMPTY JRST .+2] HRRM PKT,PKTIMP(T1) ;LINK IN HRLM PKT,CHARPQ ;TAIL OF QUEUE PION RETSKP ;ALL DONE FOR NOW >;IFN ARPAF, ;PUT PACKET AS FIRST ON Q CHAQPF: CALL NOSKDP CHKPKT ;CHECK IF DEBUGGING DEBUG,< CALL CHAQCK ;CHECK Q HEADER FOR VALIDITY JRST OKSKDP ;NO GOOD, GET OUT >;DEBUG HLRZ T1,(Q2) ;GET PRESENT HEAD HRRM T1,PKTLNK(PKT) ;PUT AS SECOND HRLM PKT,(Q2) ;PUT US AS HEAD SKIPN T1 ;AND IF EMPTY HRRM PKT,(Q2) ;AS TAIL TOO JRST OKSKDP ;PUT AS LAST ON Q CHAQPL: CALL NOSKDP CHKPKT ;CHECK PKT IF DEBUGGING DEBUG,< CALL CHAQCK ;CHECK Q HEADER JRST OKSKDP ;NO GOOD, JUST GET OUT >;DEBUG HLLZS PKTLNK(PKT) ;THIS WILL BE THE END OF A LIST HRRZ T1,(Q2) HRRM PKT,(Q2) JUMPN T1,[HRRM PKT,PKTLNK(T1) JRST OKSKDP] HRLM PKT,(Q2) ;WAS EMPTY, ON BOTH ENDS JRST OKSKDP ;GET FIRST OFF LIST CHAQGF::CALL NOSKDP DEBUG,< CALL CHAQCK ;CHECK Q HEADER JRST [ SETZ PKT, ;NO GOOD, RETURN NIL PKT REF JRST CHAQG0 ] ;JOIN EXIT CODE >;DEBUG HLRZ PKT,(Q2) JUMPE PKT,CHAQG0 HRRZ T1,PKTLNK(PKT) HLLOS PKTLNK(PKT) ;MARK AS NOT ON ANY LIST HRLM T1,(Q2) JUMPN T1,CHAQG0 SETZM (Q2) ;NOW EMPTY CHAQG0: JRST OKSKDP ;FREE RESIDENT BUFFERS CHALFR: CALL CHAQGF ;GET FIRST FROM LIST JUMPE PKT,R RCALL RELPKT,17 JRST CHALFR ;FREE RESIDENT OUTPUT BUFFERS, BUT NOT ANY THAT ARE XMIT ACTIVE CHALFO: MOVEI Q2,CHAOBF(CONN) CHALF1: CALL CHAQGF ;GET FIRST FROM LIST JUMPE PKT,R ;END OF LIST RCALL RELPKM,20 ;FREE PACKET JRST CHALF1 ;LOCK OUT SCHEDULING AND PI INTERRUPTS; CAN BE CALLED NESTEDLY. NOSKDP: AOSG CHPIDF ;IF ALREADY ACTIVE OR CONSZ PI,177B27 ; IF AT PI LEVEL, DO NOTHING RET NOSKD1 ;NO SCHEDULING PLEASE (CAN BE IN SCHEDULER) IFGE CHACHN,< CONSO PI,1B<28+CHACHN> JRST [ SETZM CHPIOF RET ] SETOM CHPIOF ;REMEMBER WE CHNOFF'ED CHNOFF CHACHN >;IFGE CHACHN, RET OKSKDP: SOSGE CHPIDF ;LEAVING THIS LEVEL OF LOCKING; IF STILL NESTED CONSZ PI,177B27 ; OR IF AT PI LEVEL, RET ; DO NOTHING OKSKD1 IFGE CHACHN,< SKIPE CHPIOF ;DID WE DO A CHNOFF? CHNON CHACHN ;YES, RESTORE STATE >;IFGE CHACHN, RET SUBTTL ARPANET ROUTING SUPPORT IFN ARPAF,< ;166 ;GET NEXT ENTRY FOR CHAOSNET ARPANET OUTPUT QUEUE ; RETURNS +1 QUEUE EMPTY ; +2 IMP BUFFER POINTER IN A CHRIMQ::HRRZ A,CHARPQ JUMPE A,R ;NONE, RETURN EMPTY HRRZ B,PKTIMP(A) ;GET LINK JUMPE B,[SETZM CHARPQ ;WAS END, QUEUE NOW EMPTY JRST .+2] HRRM B,CHARPQ ;NEW HEAD OF QUEUE HLRZ C,PKTIMP(A) ;GET ARPANET DESTINATION ADDRESS MOVEI A,PKTIMP(A) ;POINT TO IMP HEADER SETZM .NBLD0(A) ;CLEAR SPACE FOR THE 96 BIT LEADER SETZM .NBLD1(A) SETZM .NBLD2(A) MOVEI B,ITY%LL ;SET LONG LEADER FLAG STOR B,IHFTY,(A) MOVEI B,HTY%NP ;SET CONNECTION SIZE STOR B,IHHTY,(A) MOVEI B,(C) ;DESTINATION ANDI B,77 ;SIX BITS OF IMP STOR B,IHIMP,(A) LSH C,-6 ANDI C,3 ;TWO BITS OF HOST STOR C,IHHST,(A) MOVEI B,CHSLNK ;LINK STOR B,IHLNK,(A) LOAD B,CPKNB,-PKTIMP(A) ;GET BYTE COUNT ADDI B,3+*4 ;INCLUDE LENGTH OF HEADER LSH B,-2 ;INTO WORDS STOR B,NBBSZ,(A) ;AND STORE RETSKP ;MESSAGE DONE TO ARPANET INTERFACE CHIMDN::PUSH P,PKT MOVEI PKT,-PKTIMP(A) ;IF NOT RETRANSMITTABLE HRROS PKTLNK(PKT) ;CLEAR TRANSMIT ACTIVE RCALL RELPKM,21 ;CAN DEALLOCATE IT NOW POPPKJ: POP P,PKT RET ;INPUT MESSAGE FROM THE ARPANET, MAY BE IN NON-ZERO SECTION, SO ;WE CANNOT JUST CALL CPYPKT CHIIMP::PUSH P,PKT MOVE T2,IMIB ;GET POINTER TO IMP BUFFER ADDI T2,.NBHHL ;POINT TO ACTUAL DATA LOAD T1,CPKNB,(T2) ;GET BYTE COUNT ADDI T1,CHPKDT*4+3 ;PLUS PACKET HEADER LSH T1,-2 ;TURN INTO WORDS MOVEI T3,CHATPB ;THIS TEMP PACKET IS THE DESTINATION MOVEI PKT,(T3) ; AND LEAVE HERE FOR CHIPKT HRRZ T4,IMPINP ;GET NEXT WORD TO READ SUB T4,T2 ;FIGURE LENGTH TO IMP ANDI T4,-1 ;ONLY RH MEANINGFUL CAMG T1,CHPMXW ;COMPARE SIZE AGAINST MAXIMUM CAILE T1,(T4) ;COMPARE THE TWO SIZES JRST POPPKJ ;BAD, FLUSH IT CALL XBLTA ;COPY IN THE PACKET FROM IMP BUFFER PUSH P,CONN ;PRESERVE CONN HERE SE0ENT ;MAKE LIFE EASIER ON DTE CODE CALL NOSKDP ;LOCK THINGS APPROPRIATELY FOR CHIPKT CALL CHIPKT ;PROCESS INPUT OF IT CALL OKSKDP ;UNLOCK SE1ENT ;BACK TO SECTION 1 FOR IMP CODE POP P,CONN JRST POPPKJ >;166 IFN ARPAF SUBTTL DEBUGGING SUPPORT DEBUG,< ;CHECK THE CONNECTION REF'ED BY CONN FOR VALIDITY (USING MAGIC VALUE) CHKCNB: PUSH P,T2 PUSH P,T1 ;GET WORK REGISTERS MOVE T2,-2(P) ;GET CALLER'S ADDRESS+1 MOVE T1,CONMAG(CONN) ;GET MAGIC VALUE XORI T1,(CONN) ;TURN BACK INTO VANILLA MAGIC VALUE, HOPEFULLY CAME T1,[CHSMGV] ;IS IT OK? CHABUG(CHABDC,<,>) ;NO, COMPLAIN LOUDLY POP P,T1 POP P,T2 RET ;CHECK PACKET REF'ED BY PKT FOR VALIDITY CHKPKB: PUSH P,T2 HRRZ T2,-1(P) ;GET CALLER'S ADDRESS+1 (NO SECTION, FLAGS) SOS T2 ; BUMP BACK TO CHKPKB CALL POINT PUSH P,T1 PUSH P,T3 PUSH P,T4 PUSH P,Q2 MOVE T1,PKTMAG(PKT) ;GET KEYED MAGIC VALUE MOVE T4,PKTLNK(PKT) ;GET THIS FOR LATER REPORTING MOVE Q2,PKTHDW(PKT) ;GET PURPORTED ASGRES HEADER WORD MOVE T3,T1 ;SAVE IT HERE XORI T1,(PKT) ;TURN BACK INTO VANILLA VERSION CAMN Q2,-PKTHLN-1(PKT) ;IS THE HEADER WORD OK CAME T1,[CHSMGV] ; AND THE MAGIC VALUE OK? CHABUG(CHABDP,<,,,>) ;NO TO EITHER HLRZ T1,T4 ;CHECK LH OF LINK WORD CAIE T1,-1 ;THIS IS OK (INACTIVE) CAIN T1,0 ;AS IS THIS (END OF LOCAL-Q LIST) JRST CHKPBN CAIN T1,1 ;THIS IS OK (XMIT ACTIVE) JRST CHKPBN CAIL T1,RESFRP ;ELSE, MUST BE REF: CHECK RES FREE POOL CAILE T1,RESFRZ ; BOUNDS JRST CHKPBE ;OUCH, NO GOOD: COMPLAIN CHKPBN: HRRZ T1,T4 ;NOW, CHECK RH CAIE T1,-1 ;THIS IS OK (INACTIVE) CAIN T1,0 ;AS IS THIS (END OF SOME LIST) JRST CHKPBD CAIL T1,RESFRP ;ELSE, MUST BE REF: CHECK W/IN FREE POOL CAILE T1,RESFRZ ; BOUNDS CHKPBE: CHABUG(CHABDR,<,,,>) ;BAD, BARF CHKPBD: POP P,Q2 POP P,T4 ;GET BACK TEMPS POP P,T3 POP P,T1 POP P,T2 RET ;MAKE SURE WE'RE LOCKED UP: EITHER AT PI LEVEL OR HAVE CALLED NOSKDP. CHKLCK: SKIPGE CHPIDF ;HAS NOSKDP BEEN CALLED? CONSZ PI,177B27 ;NO, AT PI LEVEL? RET ;YES, WE'RE LOCKED UP CHABUG(CHALCK) ;OOPS, UNPROTECTED RET ;SET UP A PACKET HISTORY PATH ENTRY (CX HAS ENTRY) PKTPTS: PUSH P,CX ;SAVE THIS OVER POTENTIAL NOSKD1 CALL CALL NOSKDP ;DON'T LET ANYONE ELSE HACK THIS POP P,CX DPB CX,PKTHSP(PKT) ;DROP THIS IN IBP PKTHSP(PKT) ;BUMP TO NEXT HRRZ CX,PKTHSP(PKT) ;PICK UP HISTORY BYTE REF (ADDRESS ONLY) CAIL CX,PKTHSP(PKT) ;IF WE'VE GOTTEN TO THE BOTTOM, JRST [ MOVEI CX,PKTHST(PKT) ;WRAP AROUND HRLI CX,360600 MOVEM CX,PKTHSP(PKT) ;RESET IT TO TOP JRST .+1 ] CALLRET OKSKDP ;UNLOCK AND GET OUT ;SET UP A CONNECTION HISTORY ENTRY CONPTS: PUSH P,CX ;SAVE THIS OVER NOSKD1 CALL CALL NOSKDP ;DON'T LET ANYONE ELSE HACK THIS POP P,CX DPB CX,CONHSP(CONN) ;DROP THIS IN IBP CONHSP(CONN) ;BUMP TO NEXT HRRZ CX,CONHSP(CONN) ;PICK UP HISTORY BYTE REF (ADDRESS ONLY) CAIL CX,CONHSP(CONN) ;IF WE'VE GOTTEN TO THE BOTTOM, JRST [ MOVEI CX,CONHST(CONN) ;WRAP AROUND HRLI CX,331100 MOVEM CX,CONHSP(CONN) ;RESET IT TO TOP JRST .+1 ] CALLRET OKSKDP ;UNLOCK AND GET OUT ;CHECK A PACKET QUEUE HEADER TO MAKE SURE IT'S NOT MARKED AS INACTIVE CHAQCK: MOVE T1,(Q2) ;GET HEADER WORD SKIPN T1 ;OK IF NOTHING THERE RETSKP CAME T1,[-1] ;MARKED AS EMPTY? JRST [ HLRZ T1,(Q2) ;NO, PICK UP FIRST TCHKPK ; AND MAKE SURE IT'S OK HRRZ T1,(Q2) ;AND LAST TCHKPK RETSKP ] ;OK, ANYWAY CHABUG(CHAQHI) ;YES, COMPLAIN RET ;FAIL RETURN IFN T20FLG, END